<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no"><title>硅谷甄选运营平台 | XC's Blog</title><meta name="keywords" content="Vue框架笔记"><meta name="author" content="XC's Blog"><meta name="copyright" content="XC's Blog"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="#ffffff"><meta name="description" content="硅谷甄选运营平台此次教学课程为硅谷甄选运营平台项目,包含运营平台项目模板从0到1开发，以及数据大屏幕、权限等业务。 此次教学课程涉及到技术栈包含***:vue3+TypeScript+vue-router+pinia+element-plus+axios+echarts***等技术栈。 一、vue3组件通信方式通信仓库地址:https:&#x2F;&#x2F;gitee.com&#x2F;jch1011&#x2F;vue3_commun"><meta property="og:type" content="article"><meta property="og:title" content="硅谷甄选运营平台"><meta property="og:url" content="https://webxc.eu.org/post/fe33/index.html"><meta property="og:site_name" content="XC&#39;s Blog"><meta property="og:description" content="硅谷甄选运营平台此次教学课程为硅谷甄选运营平台项目,包含运营平台项目模板从0到1开发，以及数据大屏幕、权限等业务。 此次教学课程涉及到技术栈包含***:vue3+TypeScript+vue-router+pinia+element-plus+axios+echarts***等技术栈。 一、vue3组件通信方式通信仓库地址:https:&#x2F;&#x2F;gitee.com&#x2F;jch1011&#x2F;vue3_commun"><meta property="og:locale" content="zh_CN"><meta property="og:image" content="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png"><meta property="article:published_time" content="2023-07-26T03:55:00.000Z"><meta property="article:modified_time" content="2023-08-30T18:00:49.037Z"><meta property="article:author" content="XC&#39;s Blog"><meta property="article:tag" content="Vue框架笔记"><meta name="twitter:card" content="summary"><meta name="twitter:image" content="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png"><link rel="shortcut icon" href="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><link rel="canonical" href="https://webxc.eu.org/post/fe33/"><link rel="preconnect" href="//cdn.jsdelivr.net"><link rel="preconnect" href="//busuanzi.ibruce.info"><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://npm.elemecdn.com/@fortawesome/fontawesome-free@6.2.0/css/all.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://npm.elemecdn.com/node-snackbar/dist/snackbar.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://npm.elemecdn.com/@fancyapps/ui/dist/fancybox.css" media="print" onload='this.media="all"'><script>const GLOBAL_CONFIG={root:"/",algolia:void 0,localSearch:{path:"/search.xml",preload:!1,languages:{hits_empty:"找不到您查询的内容：${query}"}},translate:void 0,noticeOutdate:void 0,highlight:{plugin:"highlighjs",highlightCopy:!0,highlightLang:!0,highlightHeightLimit:!1},copy:{success:"吾辈宣布,你的剪切板已被占领",error:"呀~复制失败,请在尝试下",noSupport:"对不起,你的浏览器不支持"},relativeDate:{homepage:!1,post:!1},runtime:"",date_suffix:{just:"刚刚",min:"分钟前",hour:"小时前",day:"天前",month:"个月前"},copyright:{limitCount:60,languages:{author:"作者: XC's Blog",link:"链接: ",source:"来源: XC's Blog",info:"著作权归作者所有。商业转载请联系作者获得授权，非商业转载请注明出处。"}},lightbox:"fancybox",Snackbar:{chs_to_cht:"您已切换为繁体",cht_to_chs:"您已切换为简体",day_to_night:"您已切换为深色主题",night_to_day:"您已切换为浅色主题",bgLight:"#3b70fc",bgDark:"#121212",position:"bottom-center"},source:{justifiedGallery:{js:"https://npm.elemecdn.com/flickr-justified-gallery/dist/fjGallery.min.js",css:"https://npm.elemecdn.com/flickr-justified-gallery/dist/fjGallery.css"}},isPhotoFigcaption:!1,islazyload:!0,isAnchor:!0}</script><script id="config-diff">var GLOBAL_CONFIG_SITE={title:"硅谷甄选运营平台",isPost:!0,isHome:!1,isHighlightShrink:!1,isToc:!0,postUpdate:"2023-08-30 18:00:49"}</script><noscript><style>#nav{opacity:1}.justified-gallery img{opacity:1}#post-meta time,#recent-posts time{display:inline!important}</style></noscript><script>(e=>{e.saveToLocal={set:function(e,t,o){if(0===o)return;const n=864e5*o,a={value:t,expiry:(new Date).getTime()+n};localStorage.setItem(e,JSON.stringify(a))},get:function(e){const t=localStorage.getItem(e);if(!t)return;const o=JSON.parse(t);if(!((new Date).getTime()>o.expiry))return o.value;localStorage.removeItem(e)}},e.getScript=e=>new Promise(((t,o)=>{const n=document.createElement("script");n.src=e,n.async=!0,n.onerror=o,n.onload=n.onreadystatechange=function(){const e=this.readyState;e&&"loaded"!==e&&"complete"!==e||(n.onload=n.onreadystatechange=null,t())},document.head.appendChild(n)})),e.activateDarkMode=function(){document.documentElement.setAttribute("data-theme","dark"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#0d0d0d")},e.activateLightMode=function(){document.documentElement.setAttribute("data-theme","light"),null!==document.querySelector('meta[name="theme-color"]')&&document.querySelector('meta[name="theme-color"]').setAttribute("content","#ffffff")};const t=saveToLocal.get("theme");"dark"===t?activateDarkMode():"light"===t&&activateLightMode();const o=saveToLocal.get("aside-status");void 0!==o&&("hide"===o?document.documentElement.classList.add("hide-aside"):document.documentElement.classList.remove("hide-aside"));/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)&&document.documentElement.classList.add("apple")})(window)</script><link rel="stylesheet" href="https://cdn1.tianli0.top/gh/web-xc/My-blog-CSS/mgi.css"><link rel="stylesheet" href="https://cdn1.tianli0.top/gh/web-xc/My-blog-CSS/mg111.css"><link rel="stylesheet" href="https://npm.elemecdn.com/webxc@1.0.16/css/mg2.css"><link rel="stylesheet" href="https://npm.elemecdn.com/webxc@1.0.11/css/styless.css"><link rel="stylesheet" href="https://npm.elemecdn.com/webxc@1.0.11/css/styles.css"><link rel="stylesheet" href="https://npm.elemecdn.com/webxc@1.0.11/css/font.css"><link rel="stylesheet" href="https://npm.elemecdn.com/webxc@1.0.15/css/font2.css"><link rel="stylesheet" href="https://npm.elemecdn.com/webxc@1.0.12/css/swiper/swiper.min.css" media="print" onload='this.media="all"'><link rel="stylesheet" href="https://npm.elemecdn.com/webxc@1.0.12/css/swiper/swiperstyle.css" media="print" onload='this.media="all"'><meta name="generator" content="Hexo 6.3.0"></head><body><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg" onerror='onerror=null,src="https://npm.elemecdn.com/webxc@1.0.2/banner/404.gif"' alt="avatar"></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">95</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">25</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">25</div></a></div><hr><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw iconfont icon-shouye"></i> <span>首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw iconfont icon-shijian"></i> <span>时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw iconfont icon-biaoqian"></i> <span>标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw iconfont icon-fenlei"></i> <span>分类</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw iconfont icon-lianxiwomen"></i> <span>友联</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw iconfont icon-iconzhengli-"></i> <span>关于</span></a></div><div class="menus_item"><a class="site-page group hide" href="javascript:void(0);"><i class="fa-fw iconfont icon-a-wangzhanchaojilianjiehulianwang"></i> <span>推荐</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" target="_blank" rel="noopener" href="http://www.inode.club/"><i class="fa-fw fa-sharp fa-solid fa-square-rss"></i> <span>程序员指南</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="http://ife.baidu.com/"><i class="fa-fw fa-brands fa-vuejs"></i> <span>前端技术学园</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://www.yuque.com/tademanong/ag7q4n"><i class="fa-fw fa-solid fa-users"></i> <span>前端技术圈</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://www.code-nav.cn/"><i class="fa-fw fa-solid fa-shop"></i> <span>编程导航</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://q.shanyue.tech/"><i class="fa-fw fa-brands fa-square-js"></i> <span>每日一题</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://fanyouf.gitee.io/u1word/#/h5"><i class="fa-fw fa-solid fa-headphones"></i> <span>前端必会单词</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://site.51git.cn/render/gonav/4.html"><i class="fa-fw iconfont icon-wangzhandingzhi"></i> <span>网址导航</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://www.webxc.eu.org/music/"><i class="fa-fw iconfont icon-musical-note"></i> <span>音乐解锁</span></a></li></ul></div></div></div></div><div class="post" id="body-wrap"><header class="post-bg" id="page-header" style="background-image:url('https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png')"><nav id="nav"><span id="blog_name"><div class="back-home-button" tabindex="-1"><i class="back-home-button-icon fas fa-grip-vertical"></i><div class="back-menu-list-groups"><div class="back-menu-list-group"><div class="back-menu-list-title">项目</div><div class="back-menu-list"><a class="back-menu-item" href="/" title="前往博客主页" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">主站</span></a><a class="back-menu-item" href="https://e.webxc.eu.org/" rel="external nofollow" title="前往学习笔记" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">学习笔记</span></a><a class="back-menu-item" href="https://v.webxc.eu.org/" rel="external nofollow" title="VuePress学习文档" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">VuePress文档</span></a><a class="back-menu-item" href="https://b.webxc.eu.org/" rel="external nofollow" title="旧站Hexo" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">旧站Hexo</span></a><a class="back-menu-item" href="https://gridea.webxc.eu.org/" rel="external nofollow" title="Gridea笔记" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">Gridea笔记</span></a><a class="back-menu-item" href="https://c.webxc.eu.org/" rel="external nofollow" title="魔改Hexo" target="_blank" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">魔改Hexo</span></a></div></div><div class="back-menu-list-group"><div class="back-menu-list-title">博客镜像</div><div class="back-menu-list"><a class="back-menu-item" href="https://blog.webxc.eu.org/" title="Vercel镜像" target="_blank" rel="noopener nofollow" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">Vercel镜像</span></a><a class="back-menu-item" href="https://webxc.tk/" title="Netlify镜像" target="_blank" rel="noopener nofollow" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">Netlify镜像</span></a><a class="back-menu-item" href="https://web-xc.gitee.io/" title="Gitee镜像" target="_blank" rel="noopener nofollow" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">Gitee镜像</span></a><a class="back-menu-item" href="https://cf.webxc.eu.org/" title="Cloudflare镜像" target="_blank" rel="noopener nofollow" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">Cloudflare镜像</span></a><a class="back-menu-item" href="https://render.webxc.eu.org/" title="Render镜像" target="_blank" rel="noopener nofollow" one-link-mark="yes"><img class="back-menu-item-icon" src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg"><span class="back-menu-item-text">Render镜像</span></a></div></div></div></div><a id="site-name" href="/"><div class="title">XC's Blog</div><i class="fa-solid fa-house"></i></a></span><div class="mask-name-container"><center id="name-container"><a id="page-name" href="javascript:btf.scrollToDest(0, 500)">PAGE_NAME</a></center></div><div id="menus"><div class="nav-button" id="search-button"><a class="site-page social-icon search"><i class="fas fa-search fa-fw"></i> <span>搜索</span></a></div><div class="nav-button" id="darkmode_navswitch"><a class="darkmode_switchbutton" type="button" title="浅色和深色模式转换" onclick="switchDarkMode()"><i class="fas fa-adjust"></i></a></div><div class="nav-button" id="nav-totop"><a class="totopbtn"><i class="fas fa-arrow-up"></i><span id="percent" onclick="btf.scrollToDest(0,500)">0</span></a></div><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw iconfont icon-shouye"></i> <span>首页</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw iconfont icon-shijian"></i> <span>时间轴</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw iconfont icon-biaoqian"></i> <span>标签</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw iconfont icon-fenlei"></i> <span>分类</span></a></div><div class="menus_item"><a class="site-page" href="/link/"><i class="fa-fw iconfont icon-lianxiwomen"></i> <span>友联</span></a></div><div class="menus_item"><a class="site-page" href="/about/"><i class="fa-fw iconfont icon-iconzhengli-"></i> <span>关于</span></a></div><div class="menus_item"><a class="site-page group hide" href="javascript:void(0);"><i class="fa-fw iconfont icon-a-wangzhanchaojilianjiehulianwang"></i> <span>推荐</span><i class="fas fa-chevron-down"></i></a><ul class="menus_item_child"><li><a class="site-page child" target="_blank" rel="noopener" href="http://www.inode.club/"><i class="fa-fw fa-sharp fa-solid fa-square-rss"></i> <span>程序员指南</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="http://ife.baidu.com/"><i class="fa-fw fa-brands fa-vuejs"></i> <span>前端技术学园</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://www.yuque.com/tademanong/ag7q4n"><i class="fa-fw fa-solid fa-users"></i> <span>前端技术圈</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://www.code-nav.cn/"><i class="fa-fw fa-solid fa-shop"></i> <span>编程导航</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://q.shanyue.tech/"><i class="fa-fw fa-brands fa-square-js"></i> <span>每日一题</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://fanyouf.gitee.io/u1word/#/h5"><i class="fa-fw fa-solid fa-headphones"></i> <span>前端必会单词</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://site.51git.cn/render/gonav/4.html"><i class="fa-fw iconfont icon-wangzhandingzhi"></i> <span>网址导航</span></a></li><li><a class="site-page child" target="_blank" rel="noopener" href="https://www.webxc.eu.org/music/"><i class="fa-fw iconfont icon-musical-note"></i> <span>音乐解锁</span></a></li></ul></div></div><div id="toggle-menu"><a class="site-page"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="post-info"><h1 class="post-title">硅谷甄选运营平台</h1><div id="post-meta"><div class="meta-firstline"><span class="post-meta-date"><i class="far fa-calendar-alt fa-fw post-meta-icon"></i><span class="post-meta-label">发表于</span><time class="post-meta-date-created" datetime="2023-07-26T03:55:00.000Z" title="发表于 2023-07-26 03:55:00">2023-07-26</time><span class="post-meta-separator">|</span><i class="fas fa-history fa-fw post-meta-icon"></i><span class="post-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2023-08-30T18:00:49.037Z" title="更新于 2023-08-30 18:00:49">2023-08-30</time></span><span class="post-meta-categories"><span class="post-meta-separator">|</span><i class="fas fa-inbox fa-fw post-meta-icon"></i><a class="post-meta-categories" href="/categories/Vue%E6%A1%86%E6%9E%B6%E7%AC%94%E8%AE%B0/">Vue框架笔记</a></span></div><div class="meta-secondline"><span class="post-meta-separator">|</span><span data-flag-title="硅谷甄选运营平台"><i class="far fa-eye fa-fw post-meta-icon"></i><span class="post-meta-label">阅读量:</span><span id="twikoo_visitors"><i class="fa-solid fa-spinner fa-spin"></i></span></span></div></div></div></header><main class="layout" id="content-inner"><div id="post"><article class="post-content" id="article-container"><h1 id="硅谷甄选运营平台"><a href="#硅谷甄选运营平台" class="headerlink" title="硅谷甄选运营平台"></a>硅谷甄选运营平台</h1><p>此次教学课程为硅谷甄选运营平台项目,包含运营平台项目模板从0到1开发，以及数据大屏幕、权限等业务。</p><p>此次教学课程涉及到技术栈包含***:vue3+TypeScript+vue-router+pinia+element-plus+axios+echarts***等技术栈。</p><h2 id="一、vue3组件通信方式"><a href="#一、vue3组件通信方式" class="headerlink" title="一、vue3组件通信方式"></a>一、vue3组件通信方式</h2><p><strong>通信仓库地址:<a target="_blank" rel="noopener" href="https://gitee.com/jch1011/vue3_communication.git">https://gitee.com/jch1011/vue3_communication.git</a></strong></p><p>不管是vue2还是vue3,组件通信方式很重要,不管是项目还是面试都是经常用到的知识点。</p><p><strong>比如:vue2组件通信方式</strong></p><p>**props:**可以实现父子组件、子父组件、甚至兄弟组件通信</p><p><strong>自定义事件</strong>:可以实现子父组件通信</p><p><strong>全局事件总线$bus</strong>:可以实现任意组件通信</p><p>**pubsub:**发布订阅模式实现任意组件通信</p><p><strong>vuex</strong>:集中式状态管理容器，实现任意组件通信</p><p><strong>ref</strong>:父组件获取子组件实例VC,获取子组件的响应式数据以及方法</p><p>**slot:**插槽(默认插槽、具名插槽、作用域插槽)实现父子组件通信……..</p><h3 id="1-1props"><a href="#1-1props" class="headerlink" title="1.1props"></a>1.1props</h3><p>props可以实现父子组件通信,在vue3中我们可以通过defineProps获取父组件传递的数据。且在组件内部不需要引入defineProps方法可以直接使用！</p><p><strong>父组件给子组件传递数据</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;Child info=&quot;我爱祖国&quot; :money=&quot;money&quot;&gt;&lt;/Child&gt;</span><br></pre></td></tr></table></figure><p><strong>子组件获取父组件传递数据:方式1</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">let props = defineProps(&#123;</span><br><span class="line">  info:&#123;</span><br><span class="line">   type:String,//接受的数据类型</span><br><span class="line">   default:&#x27;默认参数&#x27;,//接受默认数据</span><br><span class="line">  &#125;,</span><br><span class="line">  money:&#123;</span><br><span class="line">   type:Number,</span><br><span class="line">   default:0</span><br><span class="line">&#125;&#125;)</span><br></pre></td></tr></table></figure><p><strong>子组件获取父组件传递数据:方式2</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">let props = defineProps([&quot;info&quot;,&#x27;money&#x27;]);</span><br></pre></td></tr></table></figure><p>子组件获取到props数据就可以在模板中使用了,但是切记props是只读的(只能读取，不能修改)</p><h3 id="1-2自定义事件"><a href="#1-2自定义事件" class="headerlink" title="1.2自定义事件"></a>1.2自定义事件</h3><p>在vue框架中事件分为两种:一种是原生的DOM事件，另外一种自定义事件。</p><p>原生DOM事件可以让用户与网页进行交互，比如click、dbclick、change、mouseenter、mouseleave….</p><p>自定义事件可以实现子组件给父组件传递数据</p><h4 id="1-2-1原生DOM事件"><a href="#1-2-1原生DOM事件" class="headerlink" title="1.2.1原生DOM事件"></a>1.2.1原生DOM事件</h4><p>代码如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;pre @click=&quot;handler&quot;&gt;</span><br><span class="line">     我是祖国的老花骨朵</span><br><span class="line">&lt;/pre&gt;</span><br></pre></td></tr></table></figure><p>当前代码级给pre标签绑定原生DOM事件点击事件,默认会给事件回调注入event事件对象。当然点击事件想注入多个参数可以按照下图操作。但是切记注入的事件对象务必叫做$event.</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;div @click=&quot;handler1(1,2,3,$event)&quot;&gt;我要传递多个参数&lt;/div&gt;</span><br></pre></td></tr></table></figure><p>在vue3框架click、dbclick、change(这类原生DOM事件),不管是在标签、自定义标签上(组件标签)都是原生DOM事件。</p><p><strong></strong></p><h4 id="1-2-2自定义事件"><a href="#1-2-2自定义事件" class="headerlink" title="1.2.2自定义事件"></a>1.2.2自定义事件</h4><p>自定义事件可以实现子组件给父组件传递数据.在项目中是比较常用的。</p><p>比如在父组件内部给子组件(Event2)绑定一个自定义事件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;Event2  @xxx=&quot;handler3&quot;&gt;&lt;/Event2&gt;</span><br></pre></td></tr></table></figure><p>在Event2子组件内部触发这个自定义事件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;h1&gt;我是子组件2&lt;/h1&gt;</span><br><span class="line">    &lt;button @click=&quot;handler&quot;&gt;点击我触发xxx自定义事件&lt;/button&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">let $emit = defineEmits([&quot;xxx&quot;]);</span><br><span class="line">const handler = () =&gt; &#123;</span><br><span class="line">  $emit(&quot;xxx&quot;, &quot;法拉利&quot;, &quot;茅台&quot;);</span><br><span class="line">&#125;;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><p>我们会发现在script标签内部,使用了defineEmits方法，此方法是vue3提供的方法,不需要引入直接使用。defineEmits方法执行，传递一个数组，数组元素即为将来组件需要触发的自定义事件类型，此方执行会返回一个$emit方法用于触发自定义事件。</p><p>当点击按钮的时候，事件回调内部调用$emit方法去触发自定义事件,第一个参数为触发事件类型，第二个、三个、N个参数即为传递给父组件的数据。</p><p>需要注意的是:代码如下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;Event2  @xxx=&quot;handler3&quot; @click=&quot;handler&quot;&gt;&lt;/Event2&gt;</span><br></pre></td></tr></table></figure><p>正常说组件标签书写@click应该为原生DOM事件,但是如果子组件内部通过defineEmits定义就变为自定义事件了</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">let $emit = defineEmits([&quot;xxx&quot;,&#x27;click&#x27;]);</span><br></pre></td></tr></table></figure><h3 id="1-3全局事件总线"><a href="#1-3全局事件总线" class="headerlink" title="1.3全局事件总线"></a>1.3全局事件总线</h3><p>全局事件总线可以实现任意组件通信，在vue2中可以根据VM与VC关系推出全局事件总线。</p><p>但是在vue3中没有Vue构造函数，也就没有Vue.prototype.以及组合式API写法没有this，</p><p>那么在Vue3想实现全局事件的总线功能就有点不现实啦，如果想在Vue3中使用全局事件总线功能</p><p>可以使用插件mitt实现。</p><p><strong>mitt:官网地址:<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/mitt">https://www.npmjs.com/package/mitt</a></strong></p><h3 id="1-4v-model"><a href="#1-4v-model" class="headerlink" title="1.4v-model"></a>1.4v-model</h3><p>v-model指令可以收集表单数据(数据双向绑定)，除此之外它也可以实现父子组件数据同步。</p><p>而v-model实指利用props[modelValue]与自定义事件[update:modelValue]实现的。</p><p>下方代码:相当于给组件Child传递一个props(modelValue)与绑定一个自定义事件update:modelValue</p><p>实现父子组件数据同步</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;Child v-model=&quot;msg&quot;&gt;&lt;/Child&gt;</span><br></pre></td></tr></table></figure><p>在vue3中一个组件可以通过使用多个v-model,让父子组件多个数据同步,下方代码相当于给组件Child传递两个props分别是pageNo与pageSize，以及绑定两个自定义事件update:pageNo与update:pageSize实现父子数据同步</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;Child v-model:pageNo=&quot;msg&quot; v-model:pageSize=&quot;msg1&quot;&gt;&lt;/Child&gt;</span><br></pre></td></tr></table></figure><h3 id="1-5useAttrs"><a href="#1-5useAttrs" class="headerlink" title="1.5useAttrs"></a>1.5useAttrs</h3><p>在Vue3中可以利用useAttrs方法获取组件的属性与事件(包含:原生DOM事件或者自定义事件),次函数功能类似于Vue2框架中$attrs属性与$listeners方法。</p><p>比如:在父组件内部使用一个子组件my-button</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;my-button type=&quot;success&quot; size=&quot;small&quot; title=&#x27;标题&#x27; @click=&quot;handler&quot;&gt;&lt;/my-button&gt;</span><br></pre></td></tr></table></figure><p>子组件内部可以通过useAttrs方法获取组件属性与事件.因此你也发现了，它类似于props,可以接受父组件传递过来的属性与属性值。需要注意如果defineProps接受了某一个属性，useAttrs方法返回的对象身上就没有相应属性与属性值。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">import &#123;useAttrs&#125; from &#x27;vue&#x27;;</span><br><span class="line">let $attrs = useAttrs();</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><h3 id="1-6ref与-parent"><a href="#1-6ref与-parent" class="headerlink" title="1.6ref与$parent"></a>1.6ref与$parent</h3><p>ref,提及到ref可能会想到它可以获取元素的DOM或者获取子组件实例的VC。既然可以在父组件内部通过ref获取子组件实例VC，那么子组件内部的方法与响应式数据父组件可以使用的。</p><p>比如:在父组件挂载完毕获取组件实例</p><p>父组件内部代码:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;h1&gt;ref与$parent&lt;/h1&gt;</span><br><span class="line">    &lt;Son ref=&quot;son&quot;&gt;&lt;/Son&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">import Son from &quot;./Son.vue&quot;;</span><br><span class="line">import &#123; onMounted, ref &#125; from &quot;vue&quot;;</span><br><span class="line">const son = ref();</span><br><span class="line">onMounted(() =&gt; &#123;</span><br><span class="line">  console.log(son.value);</span><br><span class="line">&#125;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>但是需要注意，如果想让父组件获取子组件的数据或者方法需要通过defineExpose对外暴露,因为vue3中组件内部的数据对外“关闭的”，外部不能访问</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">import &#123; ref &#125; from &quot;vue&quot;;</span><br><span class="line">//数据</span><br><span class="line">let money = ref(1000);</span><br><span class="line">//方法</span><br><span class="line">const handler = ()=&gt;&#123;</span><br><span class="line">&#125;</span><br><span class="line">defineExpose(&#123;</span><br><span class="line">  money,</span><br><span class="line">   handler</span><br><span class="line">&#125;)</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>$parent可以获取某一个组件的父组件实例VC,因此可以使用父组件内部的数据与方法。必须子组件内部拥有一个按钮点击时候获取父组件实例，当然父组件的数据与方法需要通过defineExpose方法对外暴露</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;button @click=&quot;handler($parent)&quot;&gt;点击我获取父组件实例&lt;/button&gt;</span><br></pre></td></tr></table></figure><h3 id="1-7provide与inject"><a href="#1-7provide与inject" class="headerlink" title="1.7provide与inject"></a>1.7provide与inject</h3><p><strong>provide[提供]</strong></p><p><strong>inject[注入]</strong></p><p>vue3提供两个方法provide与inject,可以实现隔辈组件传递参数</p><p>组件组件提供数据:</p><p>provide方法用于提供数据，此方法执需要传递两个参数,分别提供数据的key与提供数据value</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">import &#123;provide&#125; from &#x27;vue&#x27;</span><br><span class="line">provide(&#x27;token&#x27;,&#x27;admin_token&#x27;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><p>后代组件可以通过inject方法获取数据,通过key获取存储的数值</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">import &#123;inject&#125; from &#x27;vue&#x27;</span><br><span class="line">let token = inject(&#x27;token&#x27;);</span><br><span class="line">&lt;/script&gt;</span><br></pre></td></tr></table></figure><h3 id="1-8pinia"><a href="#1-8pinia" class="headerlink" title="1.8pinia"></a>1.8pinia</h3><p><strong>pinia官网:<a target="_blank" rel="noopener" href="https://pinia.web3doc.top/">https://pinia.web3doc.top/</a></strong></p><p>pinia也是集中式管理状态容器,类似于vuex。但是核心概念没有mutation、modules,使用方式参照官网</p><h3 id="1-9slot"><a href="#1-9slot" class="headerlink" title="1.9slot"></a>1.9slot</h3><p>插槽：默认插槽、具名插槽、作用域插槽可以实现父子组件通信.</p><p><strong>默认插槽:</strong></p><p>在子组件内部的模板中书写slot全局组件标签</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;slot&gt;&lt;/slot&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><p>在父组件内部提供结构：Todo即为子组件,在父组件内部使用的时候，在双标签内部书写结构传递给子组件</p><p>注意开发项目的时候默认插槽一般只有一个</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&lt;Todo&gt;</span><br><span class="line">  &lt;h1&gt;我是默认插槽填充的结构&lt;/h1&gt;</span><br><span class="line">&lt;/Todo&gt;</span><br></pre></td></tr></table></figure><p><strong>具名插槽：</strong></p><p>顾名思义，此插槽带有名字在组件内部留多个指定名字的插槽。</p><p>下面是一个子组件内部,模板中留两个插槽</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;h1&gt;todo&lt;/h1&gt;</span><br><span class="line">    &lt;slot name=&quot;a&quot;&gt;&lt;/slot&gt;</span><br><span class="line">    &lt;slot name=&quot;b&quot;&gt;&lt;/slot&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><p>父组件内部向指定的具名插槽传递结构。需要注意v-slot：可以替换为#</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;h1&gt;slot&lt;/h1&gt;</span><br><span class="line">    &lt;Todo&gt;</span><br><span class="line">      &lt;template v-slot:a&gt;  //可以用#a替换</span><br><span class="line">        &lt;div&gt;填入组件A部分的结构&lt;/div&gt;</span><br><span class="line">      &lt;/template&gt;</span><br><span class="line">      &lt;template v-slot:b&gt;//可以用#b替换</span><br><span class="line">        &lt;div&gt;填入组件B部分的结构&lt;/div&gt;</span><br><span class="line">      &lt;/template&gt;</span><br><span class="line">    &lt;/Todo&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">import Todo from &quot;./Todo.vue&quot;;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><p><strong>作用域插槽</strong></p><p>作用域插槽：可以理解为，子组件数据由父组件提供，但是子组件内部决定不了自身结构与外观(样式)</p><p>子组件Todo代码如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;h1&gt;todo&lt;/h1&gt;</span><br><span class="line">    &lt;ul&gt;</span><br><span class="line">     &lt;!--组件内部遍历数组--&gt;</span><br><span class="line">      &lt;li v-for=&quot;(item,index) in todos&quot; :key=&quot;item.id&quot;&gt;</span><br><span class="line">         &lt;!--作用域插槽将数据回传给父组件--&gt;</span><br><span class="line">         &lt;slot :$row=&quot;item&quot; :$index=&quot;index&quot;&gt;&lt;/slot&gt;</span><br><span class="line">      &lt;/li&gt;</span><br><span class="line">    &lt;/ul&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">defineProps([&#x27;todos&#x27;]);//接受父组件传递过来的数据</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><p>父组件内部代码如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;h1&gt;slot&lt;/h1&gt;</span><br><span class="line">    &lt;Todo :todos=&quot;todos&quot;&gt;</span><br><span class="line">      &lt;template v-slot=&quot;&#123;$row,$index&#125;&quot;&gt;</span><br><span class="line">         &lt;!--父组件决定子组件的结构与外观--&gt;</span><br><span class="line">         &lt;span :style=&quot;&#123;color:$row.done?&#x27;green&#x27;:&#x27;red&#x27;&#125;&quot;&gt;&#123;&#123;$row.title&#125;&#125;&lt;/span&gt;</span><br><span class="line">      &lt;/template&gt;</span><br><span class="line">    &lt;/Todo&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">import Todo from &quot;./Todo.vue&quot;;</span><br><span class="line">import &#123; ref &#125; from &quot;vue&quot;;</span><br><span class="line">//父组件内部数据</span><br><span class="line">let todos = ref([</span><br><span class="line">  &#123; id: 1, title: &quot;吃饭&quot;, done: true &#125;,</span><br><span class="line">  &#123; id: 2, title: &quot;睡觉&quot;, done: false &#125;,</span><br><span class="line">  &#123; id: 3, title: &quot;打豆豆&quot;, done: true &#125;,</span><br><span class="line">]);</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;style scoped&gt;</span><br><span class="line">&lt;/style&gt;</span><br></pre></td></tr></table></figure><h2 id="二、搭建后台管理系统模板"><a href="#二、搭建后台管理系统模板" class="headerlink" title="二、搭建后台管理系统模板"></a>二、搭建后台管理系统模板</h2><h3 id="2-1项目初始化"><a href="#2-1项目初始化" class="headerlink" title="2.1项目初始化"></a>2.1项目初始化</h3><p>今天来带大家从0开始搭建一个vue3版本的后台管理系统。一个项目要有统一的规范，需要使用eslint+stylelint+prettier来对我们的代码质量做检测和修复，需要使用husky来做commit拦截，需要使用commitlint来统一提交规范，需要使用preinstall来统一包管理工具。</p><p>下面我们就用这一套规范来初始化我们的项目，集成一个规范的模版。</p><h4 id="2-1-1环境准备"><a href="#2-1-1环境准备" class="headerlink" title="2.1.1环境准备"></a>2.1.1环境准备</h4><ul><li>node v16.14.2</li><li>pnpm 8.0.0</li></ul><h4 id="2-1-2初始化项目"><a href="#2-1-2初始化项目" class="headerlink" title="2.1.2初始化项目"></a>2.1.2初始化项目</h4><p>本项目使用vite进行构建，vite官方中文文档参考：<a target="_blank" rel="noopener" href="https://cn.vitejs.dev/guide/">cn.vitejs.dev&#x2F;guide&#x2F;</a></p><p><strong>pnpm:performant npm ，意味“高性能的 npm”。<a target="_blank" rel="noopener" href="https://so.csdn.net/so/search?q=pnpm&spm=1001.2101.3001.7020">pnpm</a>由npm&#x2F;yarn衍生而来，解决了npm&#x2F;yarn内部潜在的bug，极大的优化了性能，扩展了使用场景。被誉为“最先进的包管理工具”</strong></p><p>pnpm安装指令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i -g pnpm</span><br></pre></td></tr></table></figure><p>项目初始化命令:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm create vite</span><br></pre></td></tr></table></figure><p>进入到项目根目录pnpm install安装全部依赖.安装完依赖运行程序:pnpm run dev</p><p>运行完毕项目跑在<a target="_blank" rel="noopener" href="http://127.0.0.1:5173/,%E5%8F%AF%E4%BB%A5%E8%AE%BF%E9%97%AE%E4%BD%A0%E5%BE%97%E9%A1%B9%E7%9B%AE%E5%95%A6">http://127.0.0.1:5173/,可以访问你得项目啦</a></p><h3 id="2-2项目配置"><a href="#2-2项目配置" class="headerlink" title="2.2项目配置"></a>2.2项目配置</h3><h4 id="一、eslint配置"><a href="#一、eslint配置" class="headerlink" title="一、eslint配置"></a>一、eslint配置</h4><p><strong>eslint中文官网:<a target="_blank" rel="noopener" href="http://eslint.cn/">http://eslint.cn/</a></strong></p><p>ESLint最初是由<a target="_blank" rel="noopener" href="http://nczonline.net/">Nicholas C. Zakas</a> 于2013年6月创建的开源项目。它的目标是提供一个插件化的<strong>javascript代码检测工具</strong></p><p>首先安装eslint</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm i eslint -D</span><br></pre></td></tr></table></figure><p>生成配置文件:.eslint.cjs</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx eslint --init</span><br></pre></td></tr></table></figure><p><strong>.eslint.cjs配置文件</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><span class="line">module.exports = &#123;</span><br><span class="line">   //运行环境</span><br><span class="line">    &quot;env&quot;: &#123; </span><br><span class="line">        &quot;browser&quot;: true,//浏览器端</span><br><span class="line">        &quot;es2021&quot;: true,//es2021</span><br><span class="line">    &#125;,</span><br><span class="line">    //规则继承</span><br><span class="line">    &quot;extends&quot;: [ </span><br><span class="line">       //全部规则默认是关闭的,这个配置项开启推荐规则,推荐规则参照文档</span><br><span class="line">       //比如:函数不能重名、对象不能出现重复key</span><br><span class="line">        &quot;eslint:recommended&quot;,</span><br><span class="line">        //vue3语法规则</span><br><span class="line">        &quot;plugin:vue/vue3-essential&quot;,</span><br><span class="line">        //ts语法规则</span><br><span class="line">        &quot;plugin:@typescript-eslint/recommended&quot;</span><br><span class="line">    ],</span><br><span class="line">    //要为特定类型的文件指定处理器</span><br><span class="line">    &quot;overrides&quot;: [</span><br><span class="line">    ],</span><br><span class="line">    //指定解析器:解析器</span><br><span class="line">    //Esprima 默认解析器</span><br><span class="line">    //Babel-ESLint babel解析器</span><br><span class="line">    //@typescript-eslint/parser ts解析器</span><br><span class="line">    &quot;parser&quot;: &quot;@typescript-eslint/parser&quot;,</span><br><span class="line">    //指定解析器选项</span><br><span class="line">    &quot;parserOptions&quot;: &#123;</span><br><span class="line">        &quot;ecmaVersion&quot;: &quot;latest&quot;,//校验ECMA最新版本</span><br><span class="line">        &quot;sourceType&quot;: &quot;module&quot;//设置为&quot;script&quot;（默认），或者&quot;module&quot;代码在ECMAScript模块中</span><br><span class="line">    &#125;,</span><br><span class="line">    //ESLint支持使用第三方插件。在使用插件之前，您必须使用npm安装它</span><br><span class="line">    //该eslint-plugin-前缀可以从插件名称被省略</span><br><span class="line">    &quot;plugins&quot;: [</span><br><span class="line">        &quot;vue&quot;,</span><br><span class="line">        &quot;@typescript-eslint&quot;</span><br><span class="line">    ],</span><br><span class="line">    //eslint规则</span><br><span class="line">    &quot;rules&quot;: &#123;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h5 id="1-1vue3环境代码校验插件"><a href="#1-1vue3环境代码校验插件" class="headerlink" title="1.1vue3环境代码校验插件"></a>1.1vue3环境代码校验插件</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"># 让所有与prettier规则存在冲突的Eslint rules失效，并使用prettier进行代码检查</span><br><span class="line">&quot;eslint-config-prettier&quot;: &quot;^8.6.0&quot;,</span><br><span class="line">&quot;eslint-plugin-import&quot;: &quot;^2.27.5&quot;,</span><br><span class="line">&quot;eslint-plugin-node&quot;: &quot;^11.1.0&quot;,</span><br><span class="line"># 运行更漂亮的Eslint，使prettier规则优先级更高，Eslint优先级低</span><br><span class="line">&quot;eslint-plugin-prettier&quot;: &quot;^4.2.1&quot;,</span><br><span class="line"># vue.js的Eslint插件（查找vue语法错误，发现错误指令，查找违规风格指南</span><br><span class="line">&quot;eslint-plugin-vue&quot;: &quot;^9.9.0&quot;,</span><br><span class="line"># 该解析器允许使用Eslint校验所有babel code</span><br><span class="line">&quot;@babel/eslint-parser&quot;: &quot;^7.19.1&quot;,</span><br></pre></td></tr></table></figure><p>安装指令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm install -D eslint-plugin-import eslint-plugin-vue eslint-plugin-node eslint-plugin-prettier eslint-config-prettier eslint-plugin-node @babel/eslint-parser</span><br></pre></td></tr></table></figure><h5 id="1-2修改-eslintrc-cjs配置文件"><a href="#1-2修改-eslintrc-cjs配置文件" class="headerlink" title="1.2修改.eslintrc.cjs配置文件"></a>1.2修改.eslintrc.cjs配置文件</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br></pre></td><td class="code"><pre><span class="line">// @see https://eslint.bootcss.com/docs/rules/</span><br><span class="line"></span><br><span class="line">module.exports = &#123;</span><br><span class="line">  env: &#123;</span><br><span class="line">    browser: true,</span><br><span class="line">    es2021: true,</span><br><span class="line">    node: true,</span><br><span class="line">    jest: true,</span><br><span class="line">  &#125;,</span><br><span class="line">  /* 指定如何解析语法 */</span><br><span class="line">  parser: &#x27;vue-eslint-parser&#x27;,</span><br><span class="line">  /** 优先级低于 parse 的语法解析配置 */</span><br><span class="line">  parserOptions: &#123;</span><br><span class="line">    ecmaVersion: &#x27;latest&#x27;,</span><br><span class="line">    sourceType: &#x27;module&#x27;,</span><br><span class="line">    parser: &#x27;@typescript-eslint/parser&#x27;,</span><br><span class="line">    jsxPragma: &#x27;React&#x27;,</span><br><span class="line">    ecmaFeatures: &#123;</span><br><span class="line">      jsx: true,</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">  /* 继承已有的规则 */</span><br><span class="line">  extends: [</span><br><span class="line">    &#x27;eslint:recommended&#x27;,</span><br><span class="line">    &#x27;plugin:vue/vue3-essential&#x27;,</span><br><span class="line">    &#x27;plugin:@typescript-eslint/recommended&#x27;,</span><br><span class="line">    &#x27;plugin:prettier/recommended&#x27;,</span><br><span class="line">  ],</span><br><span class="line">  plugins: [&#x27;vue&#x27;, &#x27;@typescript-eslint&#x27;],</span><br><span class="line">  /*</span><br><span class="line">   * &quot;off&quot; 或 0    ==&gt;  关闭规则</span><br><span class="line">   * &quot;warn&quot; 或 1   ==&gt;  打开的规则作为警告（不影响代码执行）</span><br><span class="line">   * &quot;error&quot; 或 2  ==&gt;  规则作为一个错误（代码不能执行，界面报错）</span><br><span class="line">   */</span><br><span class="line">  rules: &#123;</span><br><span class="line">    // eslint（https://eslint.bootcss.com/docs/rules/）</span><br><span class="line">    &#x27;no-var&#x27;: &#x27;error&#x27;, // 要求使用 let 或 const 而不是 var</span><br><span class="line">    &#x27;no-multiple-empty-lines&#x27;: [&#x27;warn&#x27;, &#123; max: 1 &#125;], // 不允许多个空行</span><br><span class="line">    &#x27;no-console&#x27;: process.env.NODE_ENV === &#x27;production&#x27; ? &#x27;error&#x27; : &#x27;off&#x27;,</span><br><span class="line">    &#x27;no-debugger&#x27;: process.env.NODE_ENV === &#x27;production&#x27; ? &#x27;error&#x27; : &#x27;off&#x27;,</span><br><span class="line">    &#x27;no-unexpected-multiline&#x27;: &#x27;error&#x27;, // 禁止空余的多行</span><br><span class="line">    &#x27;no-useless-escape&#x27;: &#x27;off&#x27;, // 禁止不必要的转义字符</span><br><span class="line"></span><br><span class="line">    // typeScript (https://typescript-eslint.io/rules)</span><br><span class="line">    &#x27;@typescript-eslint/no-unused-vars&#x27;: &#x27;error&#x27;, // 禁止定义未使用的变量</span><br><span class="line">    &#x27;@typescript-eslint/prefer-ts-expect-error&#x27;: &#x27;error&#x27;, // 禁止使用 @ts-ignore</span><br><span class="line">    &#x27;@typescript-eslint/no-explicit-any&#x27;: &#x27;off&#x27;, // 禁止使用 any 类型</span><br><span class="line">    &#x27;@typescript-eslint/no-non-null-assertion&#x27;: &#x27;off&#x27;,</span><br><span class="line">    &#x27;@typescript-eslint/no-namespace&#x27;: &#x27;off&#x27;, // 禁止使用自定义 TypeScript 模块和命名空间。</span><br><span class="line">    &#x27;@typescript-eslint/semi&#x27;: &#x27;off&#x27;,</span><br><span class="line"></span><br><span class="line">    // eslint-plugin-vue (https://eslint.vuejs.org/rules/)</span><br><span class="line">    &#x27;vue/multi-word-component-names&#x27;: &#x27;off&#x27;, // 要求组件名称始终为 “-” 链接的单词</span><br><span class="line">    &#x27;vue/script-setup-uses-vars&#x27;: &#x27;error&#x27;, // 防止&lt;script setup&gt;使用的变量&lt;template&gt;被标记为未使用</span><br><span class="line">    &#x27;vue/no-mutating-props&#x27;: &#x27;off&#x27;, // 不允许组件 prop的改变</span><br><span class="line">    &#x27;vue/attribute-hyphenation&#x27;: &#x27;off&#x27;, // 对模板中的自定义组件强制执行属性命名样式</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h5 id="1-3-eslintignore忽略文件"><a href="#1-3-eslintignore忽略文件" class="headerlink" title="1.3.eslintignore忽略文件"></a>1.3.eslintignore忽略文件</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">dist</span><br><span class="line">node_modules</span><br></pre></td></tr></table></figure><h5 id="1-4运行脚本"><a href="#1-4运行脚本" class="headerlink" title="1.4运行脚本"></a>1.4运行脚本</h5><p>package.json新增两个运行脚本</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&quot;scripts&quot;: &#123;</span><br><span class="line">    &quot;lint&quot;: &quot;eslint src&quot;,</span><br><span class="line">    &quot;fix&quot;: &quot;eslint src --fix&quot;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="二、配置prettier"><a href="#二、配置prettier" class="headerlink" title="二、配置prettier"></a>二、配置<strong>prettier</strong></h4><p>有了eslint，为什么还要有prettier？eslint针对的是javascript，他是一个检测工具，包含js语法以及少部分格式问题，在eslint看来，语法对了就能保证代码正常运行，格式问题属于其次；</p><p>而prettier属于格式化工具，它看不惯格式不统一，所以它就把eslint没干好的事接着干，另外，prettier支持</p><p>包含js在内的多种语言。</p><p>总结起来，<strong>eslint和prettier这俩兄弟一个保证js代码质量，一个保证代码美观。</strong></p><h5 id="2-1安装依赖包"><a href="#2-1安装依赖包" class="headerlink" title="2.1安装依赖包"></a>2.1安装依赖包</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm install -D eslint-plugin-prettier prettier eslint-config-prettier</span><br></pre></td></tr></table></figure><h5 id="2-2-prettierrc-json添加规则"><a href="#2-2-prettierrc-json添加规则" class="headerlink" title="2.2.prettierrc.json添加规则"></a>2.2.prettierrc.json添加规则</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  &quot;singleQuote&quot;: true,</span><br><span class="line">  &quot;semi&quot;: false,</span><br><span class="line">  &quot;bracketSpacing&quot;: true,</span><br><span class="line">  &quot;htmlWhitespaceSensitivity&quot;: &quot;ignore&quot;,</span><br><span class="line">  &quot;endOfLine&quot;: &quot;auto&quot;,</span><br><span class="line">  &quot;trailingComma&quot;: &quot;all&quot;,</span><br><span class="line">  &quot;tabWidth&quot;: 2</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h5 id="2-3-prettierignore忽略文件"><a href="#2-3-prettierignore忽略文件" class="headerlink" title="2.3.prettierignore忽略文件"></a>2.3.prettierignore忽略文件</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">/dist/*</span><br><span class="line">/html/*</span><br><span class="line">.local</span><br><span class="line">/node_modules/**</span><br><span class="line">**/*.svg</span><br><span class="line">**/*.sh</span><br><span class="line">/public/*</span><br></pre></td></tr></table></figure><p><strong>通过pnpm run lint去检测语法，如果出现不规范格式,通过pnpm run fix 修改</strong></p><h4 id="三、配置stylelint"><a href="#三、配置stylelint" class="headerlink" title="三、配置stylelint"></a>三、配置stylelint</h4><p><a target="_blank" rel="noopener" href="https://stylelint.io/">stylelint</a>为css的lint工具。可格式化css代码，检查css语法错误与不合理的写法，指定css书写顺序等。</p><p>我们的项目中使用scss作为预处理器，安装以下依赖：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm add sass sass-loader stylelint postcss postcss-scss postcss-html stylelint-config-prettier stylelint-config-recess-order stylelint-config-recommended-scss stylelint-config-standard stylelint-config-standard-vue stylelint-scss stylelint-order stylelint-config-standard-scss -D</span><br></pre></td></tr></table></figure><h5 id="3-1-stylelintrc-cjs配置文件"><a href="#3-1-stylelintrc-cjs配置文件" class="headerlink" title="3.1.stylelintrc.cjs配置文件"></a>3.1<code>.stylelintrc.cjs</code><strong>配置文件</strong></h5><p><strong>官网:<a target="_blank" rel="noopener" href="https://stylelint.bootcss.com/">https://stylelint.bootcss.com/</a></strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br></pre></td><td class="code"><pre><span class="line">// @see https://stylelint.bootcss.com/</span><br><span class="line"></span><br><span class="line">module.exports = &#123;</span><br><span class="line">  extends: [</span><br><span class="line">    &#x27;stylelint-config-standard&#x27;, // 配置stylelint拓展插件</span><br><span class="line">    &#x27;stylelint-config-html/vue&#x27;, // 配置 vue 中 template 样式格式化</span><br><span class="line">    &#x27;stylelint-config-standard-scss&#x27;, // 配置stylelint scss插件</span><br><span class="line">    &#x27;stylelint-config-recommended-vue/scss&#x27;, // 配置 vue 中 scss 样式格式化</span><br><span class="line">    &#x27;stylelint-config-recess-order&#x27;, // 配置stylelint css属性书写顺序插件,</span><br><span class="line">    &#x27;stylelint-config-prettier&#x27;, // 配置stylelint和prettier兼容</span><br><span class="line">  ],</span><br><span class="line">  overrides: [</span><br><span class="line">    &#123;</span><br><span class="line">      files: [&#x27;**/*.(scss|css|vue|html)&#x27;],</span><br><span class="line">      customSyntax: &#x27;postcss-scss&#x27;,</span><br><span class="line">    &#125;,</span><br><span class="line">    &#123;</span><br><span class="line">      files: [&#x27;**/*.(html|vue)&#x27;],</span><br><span class="line">      customSyntax: &#x27;postcss-html&#x27;,</span><br><span class="line">    &#125;,</span><br><span class="line">  ],</span><br><span class="line">  ignoreFiles: [</span><br><span class="line">    &#x27;**/*.js&#x27;,</span><br><span class="line">    &#x27;**/*.jsx&#x27;,</span><br><span class="line">    &#x27;**/*.tsx&#x27;,</span><br><span class="line">    &#x27;**/*.ts&#x27;,</span><br><span class="line">    &#x27;**/*.json&#x27;,</span><br><span class="line">    &#x27;**/*.md&#x27;,</span><br><span class="line">    &#x27;**/*.yaml&#x27;,</span><br><span class="line">  ],</span><br><span class="line">  /**</span><br><span class="line">   * null  =&gt; 关闭该规则</span><br><span class="line">   * always =&gt; 必须</span><br><span class="line">   */</span><br><span class="line">  rules: &#123;</span><br><span class="line">    &#x27;value-keyword-case&#x27;: null, // 在 css 中使用 v-bind，不报错</span><br><span class="line">    &#x27;no-descending-specificity&#x27;: null, // 禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器</span><br><span class="line">    &#x27;function-url-quotes&#x27;: &#x27;always&#x27;, // 要求或禁止 URL 的引号 &quot;always(必须加上引号)&quot;|&quot;never(没有引号)&quot;</span><br><span class="line">    &#x27;no-empty-source&#x27;: null, // 关闭禁止空源码</span><br><span class="line">    &#x27;selector-class-pattern&#x27;: null, // 关闭强制选择器类名的格式</span><br><span class="line">    &#x27;property-no-unknown&#x27;: null, // 禁止未知的属性(true 为不允许)</span><br><span class="line">    &#x27;block-opening-brace-space-before&#x27;: &#x27;always&#x27;, //大括号之前必须有一个空格或不能有空白符</span><br><span class="line">    &#x27;value-no-vendor-prefix&#x27;: null, // 关闭 属性值前缀 --webkit-box</span><br><span class="line">    &#x27;property-no-vendor-prefix&#x27;: null, // 关闭 属性前缀 -webkit-mask</span><br><span class="line">    &#x27;selector-pseudo-class-no-unknown&#x27;: [</span><br><span class="line">      // 不允许未知的选择器</span><br><span class="line">      true,</span><br><span class="line">      &#123;</span><br><span class="line">        ignorePseudoClasses: [&#x27;global&#x27;, &#x27;v-deep&#x27;, &#x27;deep&#x27;], // 忽略属性，修改element默认样式的时候能使用到</span><br><span class="line">      &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h5 id="3-2-stylelintignore忽略文件"><a href="#3-2-stylelintignore忽略文件" class="headerlink" title="3.2.stylelintignore忽略文件"></a>3.2.stylelintignore忽略文件</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/node_modules/*</span><br><span class="line">/dist/*</span><br><span class="line">/html/*</span><br><span class="line">/public/*</span><br></pre></td></tr></table></figure><h5 id="3-3运行脚本"><a href="#3-3运行脚本" class="headerlink" title="3.3运行脚本"></a>3.3运行脚本</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&quot;scripts&quot;: &#123;</span><br><span class="line">	&quot;lint:style&quot;: &quot;stylelint src/**/*.&#123;css,scss,vue&#125; --cache --fix&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>最后配置统一的prettier来格式化我们的js和css，html代码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&quot;scripts&quot;: &#123;</span><br><span class="line">   &quot;dev&quot;: &quot;vite --open&quot;,</span><br><span class="line">   &quot;build&quot;: &quot;vue-tsc &amp;&amp; vite build&quot;,</span><br><span class="line">   &quot;preview&quot;: &quot;vite preview&quot;,</span><br><span class="line">   &quot;lint&quot;: &quot;eslint src&quot;,</span><br><span class="line">   &quot;fix&quot;: &quot;eslint src --fix&quot;,</span><br><span class="line">   &quot;format&quot;: &quot;prettier --write \&quot;./**/*.&#123;html,vue,ts,js,json,md&#125;\&quot;&quot;,</span><br><span class="line">   &quot;lint:eslint&quot;: &quot;eslint src/**/*.&#123;ts,vue&#125; --cache --fix&quot;,</span><br><span class="line">   &quot;lint:style&quot;: &quot;stylelint src/**/*.&#123;css,scss,vue&#125; --cache --fix&quot;</span><br><span class="line"> &#125;,</span><br></pre></td></tr></table></figure><p><strong>当我们运行<code>pnpm run format</code>的时候，会把代码直接格式化</strong></p><h4 id="四、配置husky"><a href="#四、配置husky" class="headerlink" title="四、配置husky"></a>四、配置husky</h4><p>在上面我们已经集成好了我们代码校验工具，但是需要每次手动的去执行命令才会格式化我们的代码。如果有人没有格式化就提交了远程仓库中，那这个规范就没什么用。所以我们需要强制让开发人员按照代码规范来提交。</p><p>要做到这件事情，就需要利用husky在代码提交之前触发git hook(git在客户端的钩子)，然后执行<code>pnpm run format</code>来自动的格式化我们的代码。</p><p>安装<code>husky</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm install -D husky</span><br></pre></td></tr></table></figure><p>执行</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx husky-init</span><br></pre></td></tr></table></figure><p>会在根目录下生成个一个.husky目录，在这个目录下面会有一个pre-commit文件，这个文件里面的命令在我们执行commit的时候就会执行</p><p>在<code>.husky/pre-commit</code>文件添加如下命令：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#!/usr/bin/env sh</span><br><span class="line">. &quot;$(dirname -- &quot;$0&quot;)/_/husky.sh&quot;</span><br><span class="line">pnpm run format</span><br></pre></td></tr></table></figure><p>当我们对代码进行commit操作的时候，就会执行命令，对代码进行格式化，然后再提交。</p><h4 id="五、配置commitlint"><a href="#五、配置commitlint" class="headerlink" title="五、配置commitlint"></a>五、配置commitlint</h4><p>对于我们的commit信息，也是有统一规范的，不能随便写,要让每个人都按照统一的标准来执行，我们可以利用<strong>commitlint</strong>来实现。</p><p>安装包</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm add @commitlint/config-conventional @commitlint/cli -D</span><br></pre></td></tr></table></figure><p>添加配置文件，新建<code>commitlint.config.cjs</code>(注意是cjs)，然后添加下面的代码：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">module.exports = &#123;</span><br><span class="line">  extends: [&#x27;@commitlint/config-conventional&#x27;],</span><br><span class="line">  // 校验规则</span><br><span class="line">  rules: &#123;</span><br><span class="line">    &#x27;type-enum&#x27;: [</span><br><span class="line">      2,</span><br><span class="line">      &#x27;always&#x27;,</span><br><span class="line">      [</span><br><span class="line">        &#x27;feat&#x27;,</span><br><span class="line">        &#x27;fix&#x27;,</span><br><span class="line">        &#x27;docs&#x27;,</span><br><span class="line">        &#x27;style&#x27;,</span><br><span class="line">        &#x27;refactor&#x27;,</span><br><span class="line">        &#x27;perf&#x27;,</span><br><span class="line">        &#x27;test&#x27;,</span><br><span class="line">        &#x27;chore&#x27;,</span><br><span class="line">        &#x27;revert&#x27;,</span><br><span class="line">        &#x27;build&#x27;,</span><br><span class="line">      ],</span><br><span class="line">    ],</span><br><span class="line">    &#x27;type-case&#x27;: [0],</span><br><span class="line">    &#x27;type-empty&#x27;: [0],</span><br><span class="line">    &#x27;scope-empty&#x27;: [0],</span><br><span class="line">    &#x27;scope-case&#x27;: [0],</span><br><span class="line">    &#x27;subject-full-stop&#x27;: [0, &#x27;never&#x27;],</span><br><span class="line">    &#x27;subject-case&#x27;: [0, &#x27;never&#x27;],</span><br><span class="line">    &#x27;header-max-length&#x27;: [0, &#x27;always&#x27;, 72],</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在<code>package.json</code>中配置scripts命令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 在scrips中添加下面的代码</span><br><span class="line">&#123;</span><br><span class="line">&quot;scripts&quot;: &#123;</span><br><span class="line">    &quot;commitlint&quot;: &quot;commitlint --config commitlint.config.cjs -e -V&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>配置结束，现在当我们填写<code>commit</code>信息的时候，前面就需要带着下面的<code>subject</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#x27;feat&#x27;,//新特性、新功能</span><br><span class="line">&#x27;fix&#x27;,//修改bug</span><br><span class="line">&#x27;docs&#x27;,//文档修改</span><br><span class="line">&#x27;style&#x27;,//代码格式修改, 注意不是 css 修改</span><br><span class="line">&#x27;refactor&#x27;,//代码重构</span><br><span class="line">&#x27;perf&#x27;,//优化相关，比如提升性能、体验</span><br><span class="line">&#x27;test&#x27;,//测试用例修改</span><br><span class="line">&#x27;chore&#x27;,//其他修改, 比如改变构建流程、或者增加依赖库、工具等</span><br><span class="line">&#x27;revert&#x27;,//回滚到上一个版本</span><br><span class="line">&#x27;build&#x27;,//编译相关的修改，例如发布版本、对项目构建或者依赖的改动</span><br></pre></td></tr></table></figure><p>配置husky</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npx husky add .husky/commit-msg </span><br></pre></td></tr></table></figure><p>在生成的commit-msg文件中添加下面的命令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">#!/usr/bin/env sh</span><br><span class="line">. &quot;$(dirname -- &quot;$0&quot;)/_/husky.sh&quot;</span><br><span class="line">pnpm commitlint</span><br></pre></td></tr></table></figure><p>当我们 commit 提交信息时，就不能再随意写了，必须是 git commit -m ‘fix: xxx’ 符合类型的才可以，<strong>需要注意的是类型的后面需要用英文的 :，并且冒号后面是需要空一格的，这个是不能省略的</strong></p><h4 id="六、强制使用pnpm包管理器工具"><a href="#六、强制使用pnpm包管理器工具" class="headerlink" title="六、强制使用pnpm包管理器工具"></a>六、强制使用pnpm包管理器工具</h4><p>团队开发项目的时候，需要统一包管理器工具,因为不同包管理器工具下载同一个依赖,可能版本不一样,</p><p>导致项目出现bug问题,因此包管理器工具需要统一管理！！！</p><p>在根目录创建<code>scripts/preinstall.js</code>文件，添加下面的内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">if (!/pnpm/.test(process.env.npm_execpath || &#x27;&#x27;)) &#123;</span><br><span class="line">  console.warn(</span><br><span class="line">    `\u001b[33mThis repository must using pnpm as the package manager ` +</span><br><span class="line">    ` for scripts to work properly.\u001b[39m\n`,</span><br><span class="line">  )</span><br><span class="line">  process.exit(1)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>配置命令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">&quot;scripts&quot;: &#123;</span><br><span class="line">	&quot;preinstall&quot;: &quot;node ./scripts/preinstall.js&quot;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>当我们使用npm或者yarn来安装包的时候，就会报错了。原理就是在install的时候会触发preinstall（npm提供的生命周期钩子）这个文件里面的代码。</strong></p><h2 id="三、项目集成"><a href="#三、项目集成" class="headerlink" title="三、项目集成"></a>三、项目集成</h2><h3 id="3-1集成element-plus"><a href="#3-1集成element-plus" class="headerlink" title="3.1集成element-plus"></a>3.1集成element-plus</h3><p>硅谷甄选运营平台,UI组件库采用的element-plus，因此需要集成element-plus插件！！！</p><p>官网地址:<a target="_blank" rel="noopener" href="https://element-plus.gitee.io/zh-CN/">https://element-plus.gitee.io/zh-CN/</a></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm install element-plus @element-plus/icons-vue</span><br></pre></td></tr></table></figure><p><strong>入口文件main.ts全局安装element-plus,element-plus默认支持语言英语设置为中文</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">import ElementPlus from &#x27;element-plus&#x27;;</span><br><span class="line">import &#x27;element-plus/dist/index.css&#x27;</span><br><span class="line">//@ts-ignore忽略当前文件ts类型的检测否则有红色提示(打包会失败)</span><br><span class="line">import zhCn from &#x27;element-plus/dist/locale/zh-cn.mjs&#x27;</span><br><span class="line">app.use(ElementPlus, &#123;</span><br><span class="line">    locale: zhCn</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p><strong>Element Plus全局组件类型声明</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">// tsconfig.json</span><br><span class="line">&#123;</span><br><span class="line">  &quot;compilerOptions&quot;: &#123;</span><br><span class="line">    // ...</span><br><span class="line">    &quot;types&quot;: [&quot;element-plus/global&quot;]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>配置完毕可以测试element-plus组件与图标的使用.</p><h3 id="3-2src别名的配置"><a href="#3-2src别名的配置" class="headerlink" title="3.2src别名的配置"></a>3.2src别名的配置</h3><p>在开发项目的时候文件与文件关系可能很复杂，因此我们需要给src文件夹配置一个别名！！！</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">// vite.config.ts</span><br><span class="line">import &#123;defineConfig&#125; from &#x27;vite&#x27;</span><br><span class="line">import vue from &#x27;@vitejs/plugin-vue&#x27;</span><br><span class="line">import path from &#x27;path&#x27;</span><br><span class="line">export default defineConfig(&#123;</span><br><span class="line">    plugins: [vue()],</span><br><span class="line">    resolve: &#123;</span><br><span class="line">        alias: &#123;</span><br><span class="line">            &quot;@&quot;: path.resolve(&quot;./src&quot;) // 相对路径别名配置，使用 @ 代替 src</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><p><strong>TypeScript 编译配置</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">// tsconfig.json</span><br><span class="line">&#123;</span><br><span class="line">  &quot;compilerOptions&quot;: &#123;</span><br><span class="line">    &quot;baseUrl&quot;: &quot;./&quot;, // 解析非相对模块的基地址，默认是当前目录</span><br><span class="line">    &quot;paths&quot;: &#123; //路径映射，相对于baseUrl</span><br><span class="line">      &quot;@/*&quot;: [&quot;src/*&quot;] </span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3 id="3-3环境变量的配置"><a href="#3-3环境变量的配置" class="headerlink" title="3.3环境变量的配置"></a>3.3环境变量的配置</h3><p><strong>项目开发过程中，至少会经历开发环境、测试环境和生产环境(即正式环境)三个阶段。不同阶段请求的状态(如接口地址等)不尽相同，若手动切换接口地址是相当繁琐且易出错的。于是环境变量配置的需求就应运而生，我们只需做简单的配置，把环境状态切换的工作交给代码。</strong></p><p>开发环境（development）<br>顾名思义，开发使用的环境，每位开发人员在自己的dev分支上干活，开发到一定程度，同事会合并代码，进行联调。</p><p>测试环境（testing）<br>测试同事干活的环境啦，一般会由测试同事自己来部署，然后在此环境进行测试</p><p>生产环境（production）<br>生产环境是指正式提供对外服务的，一般会关掉错误报告，打开错误日志。(正式提供给客户使用的环境。)</p><p>注意:一般情况下，一个环境对应一台服务器,也有的公司开发与测试环境是一台服务器！！！</p><p>项目根目录分别添加 开发、生产和测试环境的文件!</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">.env.development</span><br><span class="line">.env.production</span><br><span class="line">.env.test</span><br></pre></td></tr></table></figure><p>文件内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 变量必须以 VITE_ 为前缀才能暴露给外部读取</span><br><span class="line">NODE_ENV = &#x27;development&#x27;</span><br><span class="line">VITE_APP_TITLE = &#x27;硅谷甄选运营平台&#x27;</span><br><span class="line">VITE_APP_BASE_API = &#x27;/dev-api&#x27;</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">NODE_ENV = &#x27;production&#x27;</span><br><span class="line">VITE_APP_TITLE = &#x27;硅谷甄选运营平台&#x27;</span><br><span class="line">VITE_APP_BASE_API = &#x27;/prod-api&#x27;</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 变量必须以 VITE_ 为前缀才能暴露给外部读取</span><br><span class="line">NODE_ENV = &#x27;test&#x27;</span><br><span class="line">VITE_APP_TITLE = &#x27;硅谷甄选运营平台&#x27;</span><br><span class="line">VITE_APP_BASE_API = &#x27;/test-api&#x27;</span><br></pre></td></tr></table></figure><p>配置运行命令：package.json</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&quot;scripts&quot;: &#123;</span><br><span class="line">   &quot;dev&quot;: &quot;vite --open&quot;,</span><br><span class="line">   &quot;build:test&quot;: &quot;vue-tsc &amp;&amp; vite build --mode test&quot;,</span><br><span class="line">   &quot;build:pro&quot;: &quot;vue-tsc &amp;&amp; vite build --mode production&quot;,</span><br><span class="line">   &quot;preview&quot;: &quot;vite preview&quot;</span><br><span class="line"> &#125;,</span><br></pre></td></tr></table></figure><p>通过import.meta.env获取环境变量</p><h3 id="3-4SVG图标配置"><a href="#3-4SVG图标配置" class="headerlink" title="3.4SVG图标配置"></a>3.4SVG图标配置</h3><p>在开发项目的时候经常会用到svg矢量图,而且我们使用SVG以后，页面上加载的不再是图片资源,</p><p>这对页面性能来说是个很大的提升，而且我们SVG文件比img要小的很多，放在项目中几乎不占用资源。</p><p><strong>安装SVG依赖插件</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm install vite-plugin-svg-icons -D</span><br></pre></td></tr></table></figure><p><strong>在<code>vite.config.ts</code>中配置插件</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">import &#123; createSvgIconsPlugin &#125; from &#x27;vite-plugin-svg-icons&#x27;</span><br><span class="line">import path from &#x27;path&#x27;</span><br><span class="line">export default () =&gt; &#123;</span><br><span class="line">  return &#123;</span><br><span class="line">    plugins: [</span><br><span class="line">      createSvgIconsPlugin(&#123;</span><br><span class="line">        // Specify the icon folder to be cached</span><br><span class="line">        iconDirs: [path.resolve(process.cwd(), &#x27;src/assets/icons&#x27;)],</span><br><span class="line">        // Specify symbolId format</span><br><span class="line">        symbolId: &#x27;icon-[dir]-[name]&#x27;,</span><br><span class="line">      &#125;),</span><br><span class="line">    ],</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>入口文件导入</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import &#x27;virtual:svg-icons-register&#x27;</span><br></pre></td></tr></table></figure><h4 id="3-4-1svg封装为全局组件"><a href="#3-4-1svg封装为全局组件" class="headerlink" title="3.4.1svg封装为全局组件"></a>3.4.1svg封装为全局组件</h4><p>因为项目很多模块需要使用图标,因此把它封装为全局组件！！！</p><p><strong>在src&#x2F;components目录下创建一个SvgIcon组件:代表如下</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;svg :style=&quot;&#123; width: width, height: height &#125;&quot;&gt;</span><br><span class="line">      &lt;use :xlink:href=&quot;prefix + name&quot; :fill=&quot;color&quot;&gt;&lt;/use&gt;</span><br><span class="line">    &lt;/svg&gt;</span><br><span class="line">  &lt;/div&gt;</span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line">&lt;script setup lang=&quot;ts&quot;&gt;</span><br><span class="line">defineProps(&#123;</span><br><span class="line">  //xlink:href属性值的前缀</span><br><span class="line">  prefix: &#123;</span><br><span class="line">    type: String,</span><br><span class="line">    default: &#x27;#icon-&#x27;</span><br><span class="line">  &#125;,</span><br><span class="line">  //svg矢量图的名字</span><br><span class="line">  name: String,</span><br><span class="line">  //svg图标的颜色</span><br><span class="line">  color: &#123;</span><br><span class="line">    type: String,</span><br><span class="line">    default: &quot;&quot;</span><br><span class="line">  &#125;,</span><br><span class="line">  //svg宽度</span><br><span class="line">  width: &#123;</span><br><span class="line">    type: String,</span><br><span class="line">    default: &#x27;16px&#x27;</span><br><span class="line">  &#125;,</span><br><span class="line">  //svg高度</span><br><span class="line">  height: &#123;</span><br><span class="line">    type: String,</span><br><span class="line">    default: &#x27;16px&#x27;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">&#125;)</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;style scoped&gt;&lt;/style&gt;</span><br></pre></td></tr></table></figure><p>在src文件夹目录下创建一个index.ts文件：用于注册components文件夹内部全部全局组件！！！</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">import SvgIcon from &#x27;./SvgIcon/index.vue&#x27;;</span><br><span class="line">import type &#123; App, Component &#125; from &#x27;vue&#x27;;</span><br><span class="line">const components: &#123; [name: string]: Component &#125; = &#123; SvgIcon &#125;;</span><br><span class="line">export default &#123;</span><br><span class="line">    install(app: App) &#123;</span><br><span class="line">        Object.keys(components).forEach((key: string) =&gt; &#123;</span><br><span class="line">            app.component(key, components[key]);</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在入口文件引入src&#x2F;index.ts文件,通过app.use方法安装自定义插件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">import gloablComponent from &#x27;./components/index&#x27;;</span><br><span class="line">app.use(gloablComponent);</span><br></pre></td></tr></table></figure><h3 id="3-5集成sass"><a href="#3-5集成sass" class="headerlink" title="3.5集成sass"></a>3.5集成sass</h3><p>我们目前在组件内部已经可以使用scss样式,因为在配置styleLint工具的时候，项目当中已经安装过sass sass-loader,因此我们再组件内可以使用scss语法！！！需要加上lang&#x3D;”scss”</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&lt;style scoped lang=&quot;scss&quot;&gt;&lt;/style&gt;</span><br></pre></td></tr></table></figure><p>接下来我们为项目添加一些全局的样式</p><p>在src&#x2F;styles目录下创建一个index.scss文件，当然项目中需要用到清除默认样式，因此在index.scss引入reset.scss</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">@import reset.scss</span><br></pre></td></tr></table></figure><p>在入口文件引入</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">import &#x27;@/styles&#x27;</span><br></pre></td></tr></table></figure><p>但是你会发现在src&#x2F;styles&#x2F;index.scss全局样式文件中没有办法使用$变量.因此需要给项目中引入全局变量$.</p><p>在style&#x2F;variable.scss创建一个variable.scss文件！</p><p>在vite.config.ts文件配置如下:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">export default defineConfig((config) =&gt; &#123;</span><br><span class="line">	css: &#123;</span><br><span class="line">      preprocessorOptions: &#123;</span><br><span class="line">        scss: &#123;</span><br><span class="line">          javascriptEnabled: true,</span><br><span class="line">          additionalData: &#x27;@import &quot;./src/styles/variable.scss&quot;;&#x27;,</span><br><span class="line">        &#125;,</span><br><span class="line">      &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong><code>@import &quot;./src/styles/variable.less&quot;;</code>后面的<code>;</code>不要忘记，不然会报错</strong>!</p><p>配置完毕你会发现scss提供这些全局变量可以在组件样式中使用了！！！</p><h3 id="3-6mock数据"><a href="#3-6mock数据" class="headerlink" title="3.6mock数据"></a>3.6mock数据</h3><p>安装依赖:<a target="_blank" rel="noopener" href="https://www.npmjs.com/package/vite-plugin-mock">https://www.npmjs.com/package/vite-plugin-mock</a></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm install -D vite-plugin-mock mockjs</span><br></pre></td></tr></table></figure><p>在 vite.config.js 配置文件启用插件。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">import &#123; UserConfigExport, ConfigEnv &#125; from &#x27;vite&#x27;</span><br><span class="line">import &#123; viteMockServe &#125; from &#x27;vite-plugin-mock&#x27;</span><br><span class="line">import vue from &#x27;@vitejs/plugin-vue&#x27;</span><br><span class="line">export default (&#123; command &#125;)=&gt; &#123;</span><br><span class="line">  return &#123;</span><br><span class="line">    plugins: [</span><br><span class="line">      vue(),</span><br><span class="line">      viteMockServe(&#123;</span><br><span class="line">        localEnabled: command === &#x27;serve&#x27;,</span><br><span class="line">      &#125;),</span><br><span class="line">    ],</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>在根目录创建mock文件夹:去创建我们需要mock数据与接口！！！</p><p>在mock文件夹内部创建一个user.ts文件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line">//用户信息数据</span><br><span class="line">function createUserList() &#123;</span><br><span class="line">    return [</span><br><span class="line">        &#123;</span><br><span class="line">            userId: 1,</span><br><span class="line">            avatar:</span><br><span class="line">                &#x27;https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif&#x27;,</span><br><span class="line">            username: &#x27;admin&#x27;,</span><br><span class="line">            password: &#x27;111111&#x27;,</span><br><span class="line">            desc: &#x27;平台管理员&#x27;,</span><br><span class="line">            roles: [&#x27;平台管理员&#x27;],</span><br><span class="line">            buttons: [&#x27;cuser.detail&#x27;],</span><br><span class="line">            routes: [&#x27;home&#x27;],</span><br><span class="line">            token: &#x27;Admin Token&#x27;,</span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">            userId: 2,</span><br><span class="line">            avatar:</span><br><span class="line">                &#x27;https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif&#x27;,</span><br><span class="line">            username: &#x27;system&#x27;,</span><br><span class="line">            password: &#x27;111111&#x27;,</span><br><span class="line">            desc: &#x27;系统管理员&#x27;,</span><br><span class="line">            roles: [&#x27;系统管理员&#x27;],</span><br><span class="line">            buttons: [&#x27;cuser.detail&#x27;, &#x27;cuser.user&#x27;],</span><br><span class="line">            routes: [&#x27;home&#x27;],</span><br><span class="line">            token: &#x27;System Token&#x27;,</span><br><span class="line">        &#125;,</span><br><span class="line">    ]</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">export default [</span><br><span class="line">    // 用户登录接口</span><br><span class="line">    &#123;</span><br><span class="line">        url: &#x27;/api/user/login&#x27;,//请求地址</span><br><span class="line">        method: &#x27;post&#x27;,//请求方式</span><br><span class="line">        response: (&#123; body &#125;) =&gt; &#123;</span><br><span class="line">            //获取请求体携带过来的用户名与密码</span><br><span class="line">            const &#123; username, password &#125; = body;</span><br><span class="line">            //调用获取用户信息函数,用于判断是否有此用户</span><br><span class="line">            const checkUser = createUserList().find(</span><br><span class="line">                (item) =&gt; item.username === username &amp;&amp; item.password === password,</span><br><span class="line">            )</span><br><span class="line">            //没有用户返回失败信息</span><br><span class="line">            if (!checkUser) &#123;</span><br><span class="line">                return &#123; code: 201, data: &#123; message: &#x27;账号或者密码不正确&#x27; &#125; &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            //如果有返回成功信息</span><br><span class="line">            const &#123; token &#125; = checkUser</span><br><span class="line">            return &#123; code: 200, data: &#123; token &#125; &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">    // 获取用户信息</span><br><span class="line">    &#123;</span><br><span class="line">        url: &#x27;/api/user/info&#x27;,</span><br><span class="line">        method: &#x27;get&#x27;,</span><br><span class="line">        response: (request) =&gt; &#123;</span><br><span class="line">            //获取请求头携带token</span><br><span class="line">            const token = request.headers.token;</span><br><span class="line">            //查看用户信息是否包含有次token用户</span><br><span class="line">            const checkUser = createUserList().find((item) =&gt; item.token === token)</span><br><span class="line">            //没有返回失败的信息</span><br><span class="line">            if (!checkUser) &#123;</span><br><span class="line">                return &#123; code: 201, data: &#123; message: &#x27;获取用户信息失败&#x27; &#125; &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            //如果有返回成功信息</span><br><span class="line">            return &#123; code: 200, data: &#123;checkUser&#125; &#125;</span><br><span class="line">        &#125;,</span><br><span class="line">    &#125;,</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p><strong>安装axios</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pnpm install axios</span><br></pre></td></tr></table></figure><p>最后通过axios测试接口！！！</p><h3 id="3-7axios二次封装"><a href="#3-7axios二次封装" class="headerlink" title="3.7axios二次封装"></a>3.7axios二次封装</h3><p>在开发项目的时候避免不了与后端进行交互,因此我们需要使用axios插件实现发送网络请求。在开发项目的时候</p><p>我们经常会把axios进行二次封装。</p><p>目的:</p><p>1:使用请求拦截器，可以在请求拦截器中处理一些业务(开始进度条、请求头携带公共参数)</p><p>2:使用响应拦截器，可以在响应拦截器中处理一些业务(进度条结束、简化服务器返回的数据、处理http网络错误)</p><p>在根目录下创建utils&#x2F;request.ts</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">import axios from &quot;axios&quot;;</span><br><span class="line">import &#123; ElMessage &#125; from &quot;element-plus&quot;;</span><br><span class="line">//创建axios实例</span><br><span class="line">let request = axios.create(&#123;</span><br><span class="line">    baseURL: import.meta.env.VITE_APP_BASE_API,</span><br><span class="line">    timeout: 5000</span><br><span class="line">&#125;)</span><br><span class="line">//请求拦截器</span><br><span class="line">request.interceptors.request.use(config =&gt; &#123;</span><br><span class="line">    return config;</span><br><span class="line">&#125;);</span><br><span class="line">//响应拦截器</span><br><span class="line">request.interceptors.response.use((response) =&gt; &#123;</span><br><span class="line">    return response.data;</span><br><span class="line">&#125;, (error) =&gt; &#123;</span><br><span class="line">    //处理网络错误</span><br><span class="line">    let msg = &#x27;&#x27;;</span><br><span class="line">    let status = error.response.status;</span><br><span class="line">    switch (status) &#123;</span><br><span class="line">        case 401:</span><br><span class="line">            msg = &quot;token过期&quot;;</span><br><span class="line">            break;</span><br><span class="line">        case 403:</span><br><span class="line">            msg = &#x27;无权访问&#x27;;</span><br><span class="line">            break;</span><br><span class="line">        case 404:</span><br><span class="line">            msg = &quot;请求地址错误&quot;;</span><br><span class="line">            break;</span><br><span class="line">        case 500:</span><br><span class="line">            msg = &quot;服务器出现问题&quot;;</span><br><span class="line">            break;</span><br><span class="line">        default:</span><br><span class="line">            msg = &quot;无网络&quot;;</span><br><span class="line"></span><br><span class="line">    &#125;</span><br><span class="line">    ElMessage(&#123;</span><br><span class="line">        type: &#x27;error&#x27;,</span><br><span class="line">        message: msg</span><br><span class="line">    &#125;)</span><br><span class="line">    return Promise.reject(error);</span><br><span class="line">&#125;);</span><br><span class="line">export default request;</span><br></pre></td></tr></table></figure><h3 id="3-8API接口统一管理"><a href="#3-8API接口统一管理" class="headerlink" title="3.8API接口统一管理"></a>3.8API接口统一管理</h3><p>在开发项目的时候,接口可能很多需要统一管理。在src目录下去创建api文件夹去统一管理项目的接口；</p><p>比如:下面方式</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">//统一管理咱们项目用户相关的接口</span><br><span class="line"></span><br><span class="line">import request from &#x27;@/utils/request&#x27;</span><br><span class="line"></span><br><span class="line">import type &#123;</span><br><span class="line"></span><br><span class="line"> loginFormData,</span><br><span class="line"></span><br><span class="line"> loginResponseData,</span><br><span class="line"></span><br><span class="line"> userInfoReponseData,</span><br><span class="line"></span><br><span class="line">&#125; from &#x27;./type&#x27;</span><br><span class="line"></span><br><span class="line">//项目用户相关的请求地址</span><br><span class="line"></span><br><span class="line">enum API &#123;</span><br><span class="line"></span><br><span class="line"> LOGIN_URL = &#x27;/admin/acl/index/login&#x27;,</span><br><span class="line"></span><br><span class="line"> USERINFO_URL = &#x27;/admin/acl/index/info&#x27;,</span><br><span class="line"></span><br><span class="line"> LOGOUT_URL = &#x27;/admin/acl/index/logout&#x27;,</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">//登录接口</span><br><span class="line">export const reqLogin = (data: loginFormData) =&gt;</span><br><span class="line"> request.post&lt;any, loginResponseData&gt;(API.LOGIN_URL, data)</span><br><span class="line">//获取用户信息</span><br><span class="line"></span><br><span class="line">export const reqUserInfo = () =&gt;</span><br><span class="line"></span><br><span class="line"> request.get&lt;any, userInfoReponseData&gt;(API.USERINFO_URL)</span><br><span class="line"></span><br><span class="line">//退出登录</span><br><span class="line"></span><br><span class="line">export const reqLogout = () =&gt; request.post&lt;any, any&gt;(API.LOGOUT_URL)</span><br></pre></td></tr></table></figure><h2 id="四、项目的资源地址"><a href="#四、项目的资源地址" class="headerlink" title="四、项目的资源地址"></a>四、项目的资源地址</h2><p>贾成豪老师代码仓库地址:<a target="_blank" rel="noopener" href="https://gitee.com/jch1011/vue3_admin_template-bj1.git">https://gitee.com/jch1011/vue3_admin_template-bj1.git</a></p><p>项目在线文档:</p><p>服务器域名:<a target="_blank" rel="noopener" href="http://sph-api.atguigu.cn/">http://sph-api.atguigu.cn</a></p><p>swagger文档:</p><p><a target="_blank" rel="noopener" href="http://139.198.104.58:8209/swagger-ui.html">http://139.198.104.58:8209/swagger-ui.html</a></p><p><a target="_blank" rel="noopener" href="http://139.198.104.58:8212/swagger-ui.html#/">http://139.198.104.58:8212/swagger-ui.html#/</a></p><p>echarts:国内镜像网站</p><p><a target="_blank" rel="noopener" href="https://www.isqqw.com/echarts-doc/zh/option.html#title">https://www.isqqw.com/echarts-doc/zh/option.html#title</a></p><p><a target="_blank" rel="noopener" href="http://datav.aliyun.com/portal/school/atlas/area_selector">http://datav.aliyun.com/portal/school/atlas/area_selector</a></p></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">本文作者:</span> <span class="post-copyright-info"><a href="https://webxc.eu.org">XC's Blog</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">本文链接:</span> <span class="post-copyright-info"><a href="https://webxc.eu.org/post/fe33/">https://webxc.eu.org/post/fe33/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明:</span> <span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://webxc.eu.org" target="_blank">XC's Blog</a>！</span></div></div><div class="tag_share"><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/Vue%E6%A1%86%E6%9E%B6%E7%AC%94%E8%AE%B0/">Vue框架笔记</a></div><div class="post_share"><div class="social-share" data-image="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png" data-sites="facebook,twitter,wechat,weibo,qq"></div><link rel="stylesheet" href="https://npm.elemecdn.com/butterfly-extsrc/sharejs/dist/css/share.min.css" media="print" onload='this.media="all"'><script src="https://npm.elemecdn.com/butterfly-extsrc/sharejs/dist/js/social-share.min.js" defer></script></div></div><div class="post-reward"><div class="reward-button"><i class="fas fa-qrcode"></i> 打赏</div><div class="reward-main"><ul class="reward-all"><li class="reward-item"><a href="https://npm.elemecdn.com/webxc@1.0.0/lxfs/wechat.png" target="_blank"><img class="post-qr-code-img" src="https://npm.elemecdn.com/webxc@1.0.0/lxfs/wechat.png" alt="Wechat"></a><div class="post-qr-code-desc">Wechat</div></li><li class="reward-item"><a href="https://npm.elemecdn.com/webxc@1.0.0/lxfs/alipay.jpg" target="_blank"><img class="post-qr-code-img" src="https://npm.elemecdn.com/webxc@1.0.0/lxfs/alipay.jpg" alt="Alipay"></a><div class="post-qr-code-desc">Alipay</div></li></ul></div></div><nav class="pagination-post" id="pagination"><div class="prev-post pull-left"><a href="/post/ew32/"><img class="prev-cover" src="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png" onerror='onerror=null,src="https://npm.elemecdn.com/webxc@1.0.2/banner/404.gif"' alt="cover of previous post"><div class="pagination-info"><div class="label">上一篇文章</div><div class="prev_info">Vue第三天</div></div></a></div><div class="next-post pull-right"><a href="/post/ds23/"><img class="next-cover" src="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png" onerror='onerror=null,src="https://npm.elemecdn.com/webxc@1.0.2/banner/404.gif"' alt="cover of next post"><div class="pagination-info"><div class="label">下一篇文章</div><div class="next_info">常见前端面试题</div></div></a></div></nav><div class="relatedPosts"><div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>相关推荐</span></div><div class="relatedPosts-list"><div><a href="/post/465190731/" title="VueX-数组对象的双向数据绑定"><img class="cover" src="https://npm.elemecdn.com/webxc@1.0.0/cover/vuex.jpg" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2022-01-03</div><div class="title">VueX-数组对象的双向数据绑定</div></div></a></div><div><a href="/post/ou67/" title="Vue第一天"><img class="cover" src="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2023-07-14</div><div class="title">Vue第一天</div></div></a></div><div><a href="/post/fn32/" title="Vue框架笔记"><img class="cover" src="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png" alt="cover"><div class="content is-center"><div class="date"><i class="far fa-calendar-alt fa-fw"></i> 2023-07-05</div><div class="title">Vue框架笔记</div></div></a></div></div></div><hr><div id="post-comment"><div class="comment-head"><div class="comment-headline"><i class="fas fa-comments fa-fw"></i> <span>评论</span></div></div><div class="comment-wrap"><div><div id="twikoo-wrap"></div></div></div></div></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="https://npm.elemecdn.com/webxc@1.0.0/logo/logo.jpg" onerror='this.onerror=null,this.src="https://npm.elemecdn.com/webxc@1.0.2/banner/404.gif"' alt="avatar"></div><div class="author-info__name">XC's Blog</div><div class="author-info__description">XC's Blog 记录生活和学习文章</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">95</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">25</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">25</div></a></div><div class="card-info-social-icons is-center"><a class="social-icon" href="https://tenapi.cn/qqzlk/?qq=2848141597" target="_blank" title="QQ"><i class="iconfont icon-QQ"></i></a><a class="social-icon" href="https://npm.elemecdn.com/webxc@1.0.0/lxfs/wechat.jpg" target="_blank" title="微信"><i class="iconfont icon-weixin"></i></a><a class="social-icon" href="https://github.com/web-xc" target="_blank" title="Github"><i class="iconfont icon-github"></i></a><a class="social-icon" href="https://space.bilibili.com/2134826455" target="_blank" title="BiliBili"><i class="iconfont icon-bilibili"></i></a><a class="social-icon" href="https://music.163.com/#/user/home?id=323682437" target="_blank" title="网易云音乐"><i class="iconfont icon-wyy"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">原网站因使用.ml域名被回收, 再加上本人因学习原因, 没怎么打理博客, 使用了https://webxc.eu.org域名来维持博客运行, 如果有加友联的朋友们, 去友联页看信息即可, 如果原来有加过的, 麻烦在原来域名后缀改一下(.ml ==> .eu.org)就行, 博客写的太乱了, 没时间打理, 兄弟们谅解😁😁~~</div></div><div class="sticky_layout"><div class="card-widget" id="card-toc"><div class="item-headline"><i class="fas fa-stream"></i><span>目录</span><span class="toc-percentage"></span></div><div class="toc-content"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#%E7%A1%85%E8%B0%B7%E7%94%84%E9%80%89%E8%BF%90%E8%90%A5%E5%B9%B3%E5%8F%B0"><span class="toc-number">1.</span> <span class="toc-text">硅谷甄选运营平台</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%80%E3%80%81vue3%E7%BB%84%E4%BB%B6%E9%80%9A%E4%BF%A1%E6%96%B9%E5%BC%8F"><span class="toc-number">1.1.</span> <span class="toc-text">一、vue3组件通信方式</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#1-1props"><span class="toc-number">1.1.1.</span> <span class="toc-text">1.1props</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-2%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6"><span class="toc-number">1.1.2.</span> <span class="toc-text">1.2自定义事件</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2-1%E5%8E%9F%E7%94%9FDOM%E4%BA%8B%E4%BB%B6"><span class="toc-number">1.1.2.1.</span> <span class="toc-text">1.2.1原生DOM事件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#1-2-2%E8%87%AA%E5%AE%9A%E4%B9%89%E4%BA%8B%E4%BB%B6"><span class="toc-number">1.1.2.2.</span> <span class="toc-text">1.2.2自定义事件</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-3%E5%85%A8%E5%B1%80%E4%BA%8B%E4%BB%B6%E6%80%BB%E7%BA%BF"><span class="toc-number">1.1.3.</span> <span class="toc-text">1.3全局事件总线</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-4v-model"><span class="toc-number">1.1.4.</span> <span class="toc-text">1.4v-model</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-5useAttrs"><span class="toc-number">1.1.5.</span> <span class="toc-text">1.5useAttrs</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-6ref%E4%B8%8E-parent"><span class="toc-number">1.1.6.</span> <span class="toc-text">1.6ref与$parent</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-7provide%E4%B8%8Einject"><span class="toc-number">1.1.7.</span> <span class="toc-text">1.7provide与inject</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-8pinia"><span class="toc-number">1.1.8.</span> <span class="toc-text">1.8pinia</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#1-9slot"><span class="toc-number">1.1.9.</span> <span class="toc-text">1.9slot</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E6%90%AD%E5%BB%BA%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F%E6%A8%A1%E6%9D%BF"><span class="toc-number">1.2.</span> <span class="toc-text">二、搭建后台管理系统模板</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#2-1%E9%A1%B9%E7%9B%AE%E5%88%9D%E5%A7%8B%E5%8C%96"><span class="toc-number">1.2.1.</span> <span class="toc-text">2.1项目初始化</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-1%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87"><span class="toc-number">1.2.1.1.</span> <span class="toc-text">2.1.1环境准备</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#2-1-2%E5%88%9D%E5%A7%8B%E5%8C%96%E9%A1%B9%E7%9B%AE"><span class="toc-number">1.2.1.2.</span> <span class="toc-text">2.1.2初始化项目</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#2-2%E9%A1%B9%E7%9B%AE%E9%85%8D%E7%BD%AE"><span class="toc-number">1.2.2.</span> <span class="toc-text">2.2项目配置</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%80%E3%80%81eslint%E9%85%8D%E7%BD%AE"><span class="toc-number">1.2.2.1.</span> <span class="toc-text">一、eslint配置</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#1-1vue3%E7%8E%AF%E5%A2%83%E4%BB%A3%E7%A0%81%E6%A0%A1%E9%AA%8C%E6%8F%92%E4%BB%B6"><span class="toc-number">1.2.2.1.1.</span> <span class="toc-text">1.1vue3环境代码校验插件</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-2%E4%BF%AE%E6%94%B9-eslintrc-cjs%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="toc-number">1.2.2.1.2.</span> <span class="toc-text">1.2修改.eslintrc.cjs配置文件</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-3-eslintignore%E5%BF%BD%E7%95%A5%E6%96%87%E4%BB%B6"><span class="toc-number">1.2.2.1.3.</span> <span class="toc-text">1.3.eslintignore忽略文件</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#1-4%E8%BF%90%E8%A1%8C%E8%84%9A%E6%9C%AC"><span class="toc-number">1.2.2.1.4.</span> <span class="toc-text">1.4运行脚本</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BA%8C%E3%80%81%E9%85%8D%E7%BD%AEprettier"><span class="toc-number">1.2.2.2.</span> <span class="toc-text">二、配置prettier</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#2-1%E5%AE%89%E8%A3%85%E4%BE%9D%E8%B5%96%E5%8C%85"><span class="toc-number">1.2.2.2.1.</span> <span class="toc-text">2.1安装依赖包</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-2-prettierrc-json%E6%B7%BB%E5%8A%A0%E8%A7%84%E5%88%99"><span class="toc-number">1.2.2.2.2.</span> <span class="toc-text">2.2.prettierrc.json添加规则</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#2-3-prettierignore%E5%BF%BD%E7%95%A5%E6%96%87%E4%BB%B6"><span class="toc-number">1.2.2.2.3.</span> <span class="toc-text">2.3.prettierignore忽略文件</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%89%E3%80%81%E9%85%8D%E7%BD%AEstylelint"><span class="toc-number">1.2.2.3.</span> <span class="toc-text">三、配置stylelint</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#3-1-stylelintrc-cjs%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6"><span class="toc-number">1.2.2.3.1.</span> <span class="toc-text">3.1.stylelintrc.cjs配置文件</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-2-stylelintignore%E5%BF%BD%E7%95%A5%E6%96%87%E4%BB%B6"><span class="toc-number">1.2.2.3.2.</span> <span class="toc-text">3.2.stylelintignore忽略文件</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#3-3%E8%BF%90%E8%A1%8C%E8%84%9A%E6%9C%AC"><span class="toc-number">1.2.2.3.3.</span> <span class="toc-text">3.3运行脚本</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%9B%9B%E3%80%81%E9%85%8D%E7%BD%AEhusky"><span class="toc-number">1.2.2.4.</span> <span class="toc-text">四、配置husky</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BA%94%E3%80%81%E9%85%8D%E7%BD%AEcommitlint"><span class="toc-number">1.2.2.5.</span> <span class="toc-text">五、配置commitlint</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%85%AD%E3%80%81%E5%BC%BA%E5%88%B6%E4%BD%BF%E7%94%A8pnpm%E5%8C%85%E7%AE%A1%E7%90%86%E5%99%A8%E5%B7%A5%E5%85%B7"><span class="toc-number">1.2.2.6.</span> <span class="toc-text">六、强制使用pnpm包管理器工具</span></a></li></ol></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E4%B8%89%E3%80%81%E9%A1%B9%E7%9B%AE%E9%9B%86%E6%88%90"><span class="toc-number">1.3.</span> <span class="toc-text">三、项目集成</span></a><ol class="toc-child"><li class="toc-item toc-level-3"><a class="toc-link" href="#3-1%E9%9B%86%E6%88%90element-plus"><span class="toc-number">1.3.1.</span> <span class="toc-text">3.1集成element-plus</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-2src%E5%88%AB%E5%90%8D%E7%9A%84%E9%85%8D%E7%BD%AE"><span class="toc-number">1.3.2.</span> <span class="toc-text">3.2src别名的配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-3%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E7%9A%84%E9%85%8D%E7%BD%AE"><span class="toc-number">1.3.3.</span> <span class="toc-text">3.3环境变量的配置</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-4SVG%E5%9B%BE%E6%A0%87%E9%85%8D%E7%BD%AE"><span class="toc-number">1.3.4.</span> <span class="toc-text">3.4SVG图标配置</span></a><ol class="toc-child"><li class="toc-item toc-level-4"><a class="toc-link" href="#3-4-1svg%E5%B0%81%E8%A3%85%E4%B8%BA%E5%85%A8%E5%B1%80%E7%BB%84%E4%BB%B6"><span class="toc-number">1.3.4.1.</span> <span class="toc-text">3.4.1svg封装为全局组件</span></a></li></ol></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-5%E9%9B%86%E6%88%90sass"><span class="toc-number">1.3.5.</span> <span class="toc-text">3.5集成sass</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-6mock%E6%95%B0%E6%8D%AE"><span class="toc-number">1.3.6.</span> <span class="toc-text">3.6mock数据</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-7axios%E4%BA%8C%E6%AC%A1%E5%B0%81%E8%A3%85"><span class="toc-number">1.3.7.</span> <span class="toc-text">3.7axios二次封装</span></a></li><li class="toc-item toc-level-3"><a class="toc-link" href="#3-8API%E6%8E%A5%E5%8F%A3%E7%BB%9F%E4%B8%80%E7%AE%A1%E7%90%86"><span class="toc-number">1.3.8.</span> <span class="toc-text">3.8API接口统一管理</span></a></li></ol></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%9B%9B%E3%80%81%E9%A1%B9%E7%9B%AE%E7%9A%84%E8%B5%84%E6%BA%90%E5%9C%B0%E5%9D%80"><span class="toc-number">1.4.</span> <span class="toc-text">四、项目的资源地址</span></a></li></ol></li></ol></div></div><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item"><a class="thumbnail" href="/post/ds2s/" title="整个前端面试题"><img src="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png" onerror='this.onerror=null,this.src="https://npm.elemecdn.com/webxc@1.0.2/banner/404.gif"' alt="整个前端面试题"></a><div class="content"><a class="title" href="/post/ds2s/" title="整个前端面试题">整个前端面试题</a><time datetime="2023-08-31T02:00:00.000Z" title="发表于 2023-08-31 02:00:00">2023-08-31</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/post/ds23/" title="常见前端面试题"><img src="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png" onerror='this.onerror=null,this.src="https://npm.elemecdn.com/webxc@1.0.2/banner/404.gif"' alt="常见前端面试题"></a><div class="content"><a class="title" href="/post/ds23/" title="常见前端面试题">常见前端面试题</a><time datetime="2023-08-28T18:30:00.000Z" title="发表于 2023-08-28 18:30:00">2023-08-28</time></div></div><div class="aside-list-item"><a class="thumbnail" href="/post/fe33/" title="硅谷甄选运营平台"><img src="https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png" onerror='this.onerror=null,this.src="https://npm.elemecdn.com/webxc@1.0.2/banner/404.gif"' alt="硅谷甄选运营平台"></a><div class="content"><a class="title" href="/post/fe33/" title="硅谷甄选运营平台">硅谷甄选运营平台</a><time datetime="2023-07-26T03:55:00.000Z" title="发表于 2023-07-26 03:55:00">2023-07-26</time></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">&copy;2021 - 2023 By XC's Blog</div><div class="framework-info"><span></span> <a target="_blank" rel="noopener" href="https://icp.gov.moe/?keyword=20235221">萌ICP备20235221号</a><span class="footer-separator">|</span><span></span> <a target="_blank" rel="noopener" href="https://icp.gov.moe/">萌ICP查询</a><div id="running-time"></div></div><script>setInterval((()=>{let e=Math.round(new Date("2021-11-21 01:35:06").getTime()/1e3),t=Math.round(((new Date).getTime()+288e5)/1e3)-e,n=new Array(0,0,0,0,0);t>=31536e3&&(n[0]=parseInt(t/31536e3),t%=31536e3),t>=86400&&(n[1]=parseInt(t/86400),t%=86400),t>=3600&&(n[2]=parseInt(t/3600),t%=3600),t>=60&&(n[3]=parseInt(t/60),t%=60),t>0&&(n[4]=t),currentTimeHtml="本站已安全运行 "+n[0]+" 年 "+n[1]+" 天 "+n[2]+" 时 "+n[3]+" 分 "+n[4]+" 秒",document.getElementById("running-time").innerHTML=currentTimeHtml}),1e3)</script></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="readmode" type="button" title="阅读模式"><i class="fas fa-book-open"></i></button><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button class="close" id="mobile-toc-button" type="button" title="目录"><i class="fas fa-list-ul"></i></button><a id="to_comment" href="#post-comment" title="直达评论"><i class="fas fa-comments"></i></a><button id="go-up" type="button" title="回到顶部"><i class="fas fa-arrow-up"></i><span id="percent">0<span>%</span></span></button><button id="go-down" type="button" title="直达底部" onclick="btf.scrollToDest(document.body.scrollHeight,500)"><i class="fas fa-arrow-down"></i></button></div></div><div id="local-search"><div class="search-dialog"><nav class="search-nav"><span class="search-dialog-title">搜索</span><span id="loading-status"></span><button class="search-close-button"><i class="fas fa-times"></i></button></nav><div class="is-center" id="loading-database"><i class="fas fa-spinner fa-pulse"></i> <span>正在载入文件,请稍后</span></div><div class="search-wrap"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章" type="text"></div></div><hr><div id="local-search-results"></div></div></div><div id="search-mask"></div></div><div><script src="https://npm.elemecdn.com/hexo-theme-butterfly/source/js/utils.js"></script><script src="https://npm.elemecdn.com/hexo-theme-butterfly@4.4.0/source/js/main.js"></script><script src="https://npm.elemecdn.com/@fancyapps/ui/dist/fancybox.umd.js"></script><script src="https://npm.elemecdn.com/instant.page/instantpage.js" type="module"></script><script src="https://npm.elemecdn.com/vanilla-lazyload/dist/lazyload.iife.min.js"></script><script src="https://npm.elemecdn.com/node-snackbar/dist/snackbar.min.js"></script><script src="https://npm.elemecdn.com/hexo-theme-butterfly/source/js/search/local-search.js"></script><div class="js-pjax"><script>(()=>{const e=document.querySelectorAll("#article-container .mermaid-wrap");if(e.length){window.runMermaid=()=>{window.loadMermaid=!0;const t="dark"===document.documentElement.getAttribute("data-theme")?"dark":"default";Array.from(e).forEach(((e,n)=>{const d=e.firstElementChild,r="mermaid-"+n,m="%%{init:{ 'theme':'"+t+"'}}%%\n"+d.textContent;mermaid.mermaidAPI.render(r,m,(e=>{d.insertAdjacentHTML("afterend",e)}))}))};const t=()=>{window.loadMermaid?runMermaid():getScript("https://npm.elemecdn.com/mermaid/dist/mermaid.min.js").then(runMermaid)};window.pjax?t():document.addEventListener("DOMContentLoaded",t)}})()</script><script>(()=>{const o=()=>{twikoo.init(Object.assign({el:"#twikoo-wrap",envId:"https://blog2.webxc.eu.org/",region:"",onCommentLoaded:function(){btf.loadLightbox(document.querySelectorAll("#twikoo .tk-content img:not(.tk-owo-emotion)"))}},null))},t=()=>{"object"!=typeof twikoo?getScript("https://npm.elemecdn.com/twikoo@1.6.16/dist/twikoo.all.min.js").then(o):setTimeout(o,0)};t()})()</script></div><script data-pjax="false" defer src="https://npm.elemecdn.com/webxc@1.0.16/css/style.js"></script><script defer src="https://npm.elemecdn.com/hexo-theme-butterfly@4.4.0/source/js/search/local-search.js"></scrip><script src="https://npm.elemecdn.com/butterfly-extsrc/dist/activate-power-mode.min.js"></script><script>POWERMODE.colorful=!0,POWERMODE.shake=!0,POWERMODE.mobile=!0,document.body.addEventListener("input",POWERMODE)</script><script src="https://npm.elemecdn.com/pjax@0.2.8/pjax.min.js"></script><script>let pjaxSelectors=["head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax",".tk-comments-container"];var pjax=new Pjax({elements:'a:not([target="_blank"])',selectors:pjaxSelectors,cacheBust:!1,analytics:!1,scrollRestoration:!1});document.addEventListener("pjax:send",(function(){if(window.tocScrollFn&&window.removeEventListener("scroll",window.tocScrollFn),window.scrollCollect&&window.removeEventListener("scroll",scrollCollect),"object"==typeof preloader&&preloader.initLoading(),document.getElementById("rightside").style.cssText="opacity: ''; transform: ''",window.aplayers)for(let e=0;e<window.aplayers.length;e++)window.aplayers[e].options.fixed||window.aplayers[e].destroy();"object"==typeof typed&&typed.destroy();const e=document.body.classList;e.contains("read-mode")&&e.remove("read-mode"),"object"==typeof disqusjs&&disqusjs.destroy()})),document.addEventListener("pjax:complete",(function(){window.refreshFn(),document.querySelectorAll("script[data-pjax]").forEach((e=>{const t=document.createElement("script"),o=e.text||e.textContent||e.innerHTML||"";Array.from(e.attributes).forEach((e=>t.setAttribute(e.name,e.value))),t.appendChild(document.createTextNode(o)),e.parentNode.replaceChild(t,e)})),GLOBAL_CONFIG.islazyload&&window.lazyLoadInstance.update(),"function"==typeof chatBtnFn&&chatBtnFn(),"function"==typeof panguInit&&panguInit(),"function"==typeof gtag&&gtag("config","",{page_path:window.location.pathname}),"object"==typeof _hmt&&_hmt.push(["_trackPageview",window.location.pathname]),"function"==typeof loadMeting&&document.getElementsByClassName("aplayer").length&&loadMeting(),"object"==typeof Prism&&Prism.highlightAll(),"object"==typeof preloader&&preloader.endLoading()})),document.addEventListener("pjax:error",(e=>{404===e.request.status&&pjax.loadUrl("/404.html")}))</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div><script data-pjax>function butterfly_swiper_injector_config(){var s=document.getElementById("recent-posts");console.log("已挂载butterfly_swiper"),s.insertAdjacentHTML("afterbegin",'<div class="recent-post-item" style="height: auto;width: 100%"><div class="blog-slider swiper-container-fade swiper-container-horizontal" id="swiper_container"><div class="blog-slider__wrp swiper-wrapper" style="transition-duration: 0ms;"><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-08-31</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/ds2s/&quot;);" href="javascript:void(0);" alt="">整个前端面试题</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-08-28</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/ds23/&quot;);" href="javascript:void(0);" alt="">常见前端面试题</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-07-26</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/fe33/&quot;);" href="javascript:void(0);" alt="">硅谷甄选运营平台</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-07-17</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/ew32/&quot;);" href="javascript:void(0);" alt="">Vue第三天</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-07-16</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/aw92/&quot;);" href="javascript:void(0);" alt="">Vue第二天</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-07-14</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/ou67/&quot;);" href="javascript:void(0);" alt="">Vue第一天</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/vue.png);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-07-05</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/fn32/&quot;);" href="javascript:void(0);" alt="">Vue框架笔记</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://npm.elemecdn.com/webxc/cover/js1.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-06-21</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/fe11/&quot;);" href="javascript:void(0);" alt="">Vue前置JS功底</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/promise.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-06-11</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/pr67/&quot;);" href="javascript:void(0);" alt="">ES6-Promise语法与原理</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/ajax.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-06-08</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/or01/&quot;);" href="javascript:void(0);" alt="">Ajax第四天</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://cdn1.tianli0.top/gh/web-xc/iMG/postss/ajax.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-06-07</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/fs67/&quot;);" href="javascript:void(0);" alt="">Ajax第三天</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://npm.elemecdn.com/webxc/cover/js1.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-05-11</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/fe66/&quot;);" href="javascript:void(0);" alt="">JS进阶第四天</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://npm.elemecdn.com/webxc/cover/js1.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-05-10</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/fe99/&quot;);" href="javascript:void(0);" alt="">JS进阶第三天</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://npm.elemecdn.com/webxc/cover/js1.webp);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2023-05-05</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/us87/&quot;);" href="javascript:void(0);" alt="">JS进阶第二天</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://npm.elemecdn.com/webxc@1.0.12/cover/cover15.jpg);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2022-10-31</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/2db5/&quot;);" href="javascript:void(0);" alt="">移动开发-Flex布局</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://npm.elemecdn.com/webxc@1.0.12/cover/cover16.jpg);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2022-11-14</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/1c7e/&quot;);" href="javascript:void(0);" alt="">移动开发-媒体查询</a><div class="blog-slider__text">点击查看</div></div></div><div class="blog-slider__item swiper-slide" style="background:url(https://npm.elemecdn.com/webxc@1.0.12/cover/cover17.jpg);border-radius:12px;opacity: 1; transform: translate3d(0px, 0px, 0px); transition-duration: 0ms;"><div class="blog-slider__content"><span class="blog-slider__code">2022-11-17</span><a class="blog-slider__title" onclick="pjax.loadUrl(&quot;post/7fc/&quot;);" href="javascript:void(0);" alt="">移动开发-响应式</a><div class="blog-slider__text">点击查看</div></div></div></div><div class="blog-slider__pagination swiper-pagination-clickable swiper-pagination-bullets"></div><div class="swiper-button-prev"></div><div class="swiper-button-next"></div></div></div>')}for(var elist="null".split(","),cpage=location.pathname,epage="all",flag=0,i=0;i<elist.length;i++)cpage.includes(elist[i])&&flag++;("all"===epage&&0==flag||epage===cpage)&&butterfly_swiper_injector_config()</script><script defer src="https://npm.elemecdn.com/webxc@1.0.12/css/swiper/swiper.min.js"></script><script defer data-pjax src="https://npm.elemecdn.com/webxc@1.0.12/css/swiper/swiper_init.js"></script></body></html>